Skip to content

块级作用域诞生

在ES6之前,通过var关键字声明变量

js
    if(false){
        var value = 100;
    }
    console.log(value)

初学者可能会觉得条件为false,value不可能被创建,结果应该是报错,然而因为变量提升的原因,代码相当于:

js
    var value;
    if(false){
        value = 100;
    }
    console.log(value); // undefined

除此之外,在 for 循环中:

js
    for (var i = 0; i < 10; i++) {
        ...
    }
    console.log(i); // 10

即便循环已经结束了,我们依然可以访问 i 的值。

为了加强对变量生命周期的控制,ECMAScript 6 引入了块级作用域。

块级作用域存在于:

  • 函数内部
  • 块中(字符 { 和 } 之间的区域)

let 和 const

块级声明用于声明在指定块的作用域之外无法访问的变量,let 和 const 都是块级声明的一种。

let 和 const的共同特点

1.不会被提升

js
    if (false) {
        let value = 1;
    }
    console.log(value); // Uncaught ReferenceError: value is not defined

2.重复声明报错

js
var value = 1;
let value = 2; // Uncaught SyntaxError: Identifier 'value' has already been declared

3.不绑定全局作用域

当在全局作用域中使用 var 声明的时候,会创建一个新的全局变量作为全局对象的属性。

js
var value = 1;
console.log(window.value); // 1

let 和 const 不会这样:

js
let value = 1;
console.log(window.value); // undefined

let 和 const 的区别

const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容。

js
const data = {
    value: 1
}

// 没有问题
data.value = 2;
data.num = 3;

// 报错
data = {}; // Uncaught TypeError: Assignment to constant variable.

暂时性死区

临时死区(Temporal Dead Zone),简写为 TDZ

let 和 const 声明的变量不会被提升到作用域顶部,如果在声明之前访问这些变量,会导致报错:

js
console.log(typeof value); // Uncaught ReferenceError: value is not defined
let value = 1;

这是因为 JavaScript 引擎在扫描代码发现变量声明时,要么将它们提升到作用域顶部(遇到 var 声明),要么将声明放在 TDZ 中(遇到 let 和 const 声明)。访问 TDZ 中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从 TDZ 中移出,然后方可访问。

tdz