var 和 let 之間的區別

(注意:使用 let 的所有示例也適用於 const

var 適用於所有版本的 JavaScript,而 letconst 是 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"

請注意,ij 僅在 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,但是如果內部塊具有 ilet 宣告,則無法訪問外部 i,如果在宣告第二個宣告之前使用了 ReferenceError,則會丟擲 ReferenceError

let i = 5;
{
    i = 6;  // outer i is unavailable within the Temporal Dead Zone
    let i;
}

ReferenceError:我沒有定義

吊裝

varlet 宣告的變數都被懸掛 。不同之處在於,使用 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;

塊的開始和 letconst 宣告之間的區域稱為時間死區 ,並且對該區域中的變數的任何引用都將導致 ReferenceError。即使在宣告變數之前分配變數,也會發生這種情況 :

y=7; // >> "ReferenceError: `y` is not defined"
let y;

在非嚴格模式下,在沒有任何宣告的情況下為變數賦值,會自動在全域性範圍內宣告變數 。在這種情況下,let 不是在全域性範圍內自動宣告 y,而是保留變數的名稱(y),並且在宣告/初始化它之前不允許對它進行任何訪問或賦值。