JavaScript中var與let的異同點

聽寒以南發表於2021-12-08

var是JavaScript剛出現時就存在的變數宣告關鍵字,而let作為ES6才出現的變數宣告關鍵字,無疑兩者之間存在著很大的區別。那麼具體有哪些區別呢?

1.作用域表現形式不同,var是函式作用域,let是塊級作用域

{
  var monkey='薰悟空';
  let pig='豬扒蓋';    
}
console.log(monkey); //輸出undefined
console.log(pig); //報錯:pig is not deined

由上面程式碼可見,let宣告的變數只在其所在的程式碼塊有效,在程式碼塊外部無效無法訪問,而var宣告的變數在該程式碼塊所在的函式作用域內都有效。

 

2.是否變數提升的區別,var宣告的變數會進行變數提升,let宣告的變數不會進行變數提升。

console.log(monkey); //undefined
var monkey='薰悟空';

console.log(pig); //報錯:pig is not defined
let pig='豬扒蓋'; 

同樣的邏輯,為什麼var宣告的變數在它宣告之前呼叫會顯示未定義,而let宣告的變數在宣告之前呼叫會丟擲異常呢,這就是兩者在變數提升上的區別,var宣告的變數存在變數提升,let宣告的變數不存在變數提升。

那麼什麼叫變數提升呢,我這裡不做概念性的描述,我只說我個人的理解,就是以上程式碼實際上相當於如下:

var monkey;

console.log(monkey); //undefined
monkey='薰悟空';

console.log(pig); //報錯:pig is not defined
let pig='豬扒蓋'; 

看見區別了嗎,var宣告的變數會將宣告的變數提取到作用域的最上面進行定義但不賦值,賦值操作還是在你的程式碼處,所以你在呼叫var宣告的變數時就是一個已經宣告但是並未定義值的變數,所以呼叫結果就是undefined,這就是所謂的變數提升。而let定義的變數不存在這種變數提升。

 

3.暫時性死區上的區別

暫時性死區:如果在某一作用域內let了一個變數,如果外部作用域中有相同名稱的變數,那麼就算在作用域內進行了更改,也不會影響到外部作用域

具體表現如下:

for(var i=0;i<5;i++){
    setTimeout(function(){
        console.log(i)
    },1000)
}
for(let i=0;i<5;i++){
  setTimeout(function(){
     console.log(i)          
  },1000)  
}

請問這兩處程式碼的執行結果分別是什麼?

第一處程式碼執行完畢的結果是1s後順序列印5個5;第二處程式碼執行完畢的結果是1s後順序列印0,1,2,3,4。

請問為什麼會存在這種區別?

因為第一處程式碼的變數i由var關鍵字宣告,不存在關鍵性死區,即你在1s後setTimeout中訪問到的變數i是全域性上下文中for迴圈執行完畢之後的i,所以列印的結果全是5;

而第二處程式碼的變數i由let關鍵字宣告,產生了關鍵性死區,存在setTimeout中的i變數是你當時儲存時的i的值,這個儲存區間的i不會因為外面有相同的i變數且賦了不同的值而改變,他依舊是之前儲存進去的值,這就是暫時性死區的表現,也是為什麼第二處程式碼執行完畢是順序列印0,1,2,3,4的原因。

 

4.在同一個上下文中var可以重複宣告,let不行

let monkey='薰悟空';
let monkey='逼馬吻'; //報錯:Identifier 'a' has already been declared
var pig='豬扒蓋';
var pig='豬肛裂';  //正常訪問,變數pig的值被替換

相關文章