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),并且在声明/初始化它之前不允许对它进行任何访问或赋值。