var 和 let 之間的區別
(注意:使用 let
的所有示例也適用於 const
)
var
適用於所有版本的 JavaScript,而 let
和 const
是 ECMAScript 6 的一部分,僅在某些較新的瀏覽器中可用 。
var
的範圍限定為包含函式或全域性空間,具體取決於何時宣告:
var x = 4; // global scope
function DoThings() {
var x = 7; // function scope
console.log(x);
}
console.log(x); // >> 4
DoThings(); // >> 7
console.log(x); // >> 4
這意味著它轉義if
語句和所有類似的塊結構:
var x = 4;
if (true) {
var x = 7;
}
console.log(x); // >> 7
for (var i = 0; i < 4; i++) {
var j = 10;
}
console.log(i); // >> 4
console.log(j); // >> 10
相比之下,let
是塊作用域:
let x = 4;
if (true) {
let x = 7;
console.log(x); // >> 7
}
console.log(x); // >> 4
for (let i = 0; i < 4; i++) {
let j = 10;
}
console.log(i); // >> "ReferenceError: i is not defined"
console.log(j); // >> "ReferenceError: j is not defined"
請注意,i
和 j
僅在 for
迴圈中宣告,因此在其外部未宣告。
還有其他幾個重要的區別:
全域性變數宣告
在頂層作用域(在任何函式和塊之外),var
宣告將一個元素放在全域性物件中。let
沒有:
var x = 4;
let y = 7;
console.log(this.x); // >> 4
console.log(this.y); // >> undefined
重新申報
使用 var
宣告變數兩次不會產生錯誤(即使它相當於宣告一次):
var x = 4;
var x = 7;
使用 let
,會產生錯誤:
let x = 4;
let x = 7;
TypeError:識別符號
x
已經宣告
使用 var
宣告 y
時也是如此:
var y = 4;
let y = 7;
TypeError:識別符號
y
已經宣告
但是,使用 let 宣告的變數可以在巢狀塊中重用(不重新宣告)
let i = 5;
{
let i = 6;
console.log(i); // >> 6
}
console.log(i); // >> 5
在塊內可以訪問外部 i
,但是如果內部塊具有 i
的 let
宣告,則無法訪問外部 i
,如果在宣告第二個宣告之前使用了 ReferenceError
,則會丟擲 ReferenceError
。
let i = 5;
{
i = 6; // outer i is unavailable within the Temporal Dead Zone
let i;
}
ReferenceError:我沒有定義
吊裝
用 var
和 let
宣告的變數都被懸掛 。不同之處在於,使用 var
宣告的變數可以在其自己的賦值之前引用,因為它會自動賦值(以 undefined
作為其值),但是 let
不能 - 它特別要求在呼叫之前宣告變數:
console.log(x); // >> undefined
console.log(y); // >> "ReferenceError: `y` is not defined"
//OR >> "ReferenceError: can't access lexical declaration `y` before initialization"
var x = 4;
let y = 7;
塊的開始和 let
或 const
宣告之間的區域稱為時間死區 ,並且對該區域中的變數的任何引用都將導致 ReferenceError
。即使在宣告變數之前分配變數,也會發生這種情況 :
y=7; // >> "ReferenceError: `y` is not defined"
let y;
在非嚴格模式下,在沒有任何宣告的情況下為變數賦值,會自動在全域性範圍內宣告變數 。在這種情況下,let
不是在全域性範圍內自動宣告 y
,而是保留變數的名稱(y
),並且在宣告/初始化它之前不允許對它進行任何訪問或賦值。