let和var的區別
1. 通過var關鍵字聲明的變量沒有塊作用域,在塊{ }內聲明的變量可以從塊之外進行訪問。
通過let關鍵字聲明的變量擁有塊作用域,在塊{ }內聲明的變量無法從塊外訪問
eg:
{ var x = 10; } // 此處可以使用 x { let x = 10; } // 此處不可以使用 x
2. 通過var關鍵字重新聲明變量會帶來問題,在塊中聲明變量也將重新聲明塊外的變量,覆蓋塊外的變量
通過let關鍵字重新聲明的變量不會重新聲明塊外的變量,會重新聲明一個有塊作用域的變量
eg:
var x = 10; // 此處 x 為 10 { var x = 6; // 此處 x 為 6 } // 此處 x 為 6
var x = 10; // 此處 x 為 10 { let x = 6; // 此處 x 為 6 } // 此處 x 為 10
3. 通過var關鍵字在循環中使用會重新聲明循環之外的變量,覆蓋循環之外的變量,會保存循環內對變量的改變
通過let關鍵字在循環中使用不會重新聲明循環之外的變量,會重新聲明一個有塊作用域的變量,並且不會保存循環內對變量的改變
eg:
var i = 7; for (var i = 0; i < 10; i++) { // 一些語句 } // 此處,i 為 10
let i = 7; for (let i = 0; i < 10; i++) { // 一些語句 } // 此處 i 為 7
4. 通過 var 關鍵詞定義的全局變量屬於 window 對象
通過 let 關鍵詞定義的全局變量不屬於 window 對象
eg:
var carName = "porsche"; // 此處的代碼可使用 window.carName
let carName = "porsche"; // 此處的代碼不可使用 window.carName
5. 通過 var 聲明的變量會提升到頂端
通過 let 定義的變量不會被提升到頂端,在聲明 let 變量之前就使用它會導致 ReferenceError,變量從塊的開頭一直處於“暫時性死區”,直到聲明為止。 let要求必須 等let
聲明語句執行完之后,變量才能使用
在代碼塊內,使用let
命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。
暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,才可以獲取和 使用該變量。
eg:
// var 的情況 console.log(foo); // 輸出undefined var foo = 2; // let 的情況 console.log(bar); // 報錯ReferenceError let bar = 2;
有一部分死區很難發現
eg:
function bar(x = y, y = 2) { return [x, y]; } bar();//報錯,因為x=y時,y還沒有聲明屬於死區
想反,下面這種情況就不會報錯。
function bar(x = 2, y = x) { return [x, y]; } bar(); // [2, 2]
let和var的共同點
在函數內聲明變量時,使用 var 和 let 很相似,它們都有函數作用域
如果在塊外聲明聲明,那么 var 和 let 也很相似,它們都擁有全局作用域
注:
允許在程序的任何位置使用 var 重新聲明 JavaScript 變量
在相同的作用域,或在相同的塊中,通過 let 重新聲明一個 var 變量是不允許的
在相同的作用域,或在相同的塊中,通過 let 重新聲明一個 let 變量是不允許的
在相同的作用域,或在相同的塊中,通過 var 重新聲明一個 let 變量是不允許的
在不同的作用域或塊中,通過 let 重新聲明變量是允許的
不能在函數內聲明參數
eg:
function func(arg) { let arg; } func() // 報錯 function func(arg) { { let arg; } } func() // 不報錯