9.4 暂时性死区(temporal dead zone)

letconst 声明的变量拥有暂时性死区(TDZ):当进入它的作用域,它不能被访问(获取或设置)直到执行到达声明。

首先看看不具有暂时性死区的 var

  • 当进入 var 变量的作用域(包围它的函数),立即为它创建(绑定)存储空间。变量会立即被初始化并赋值为 undefined
  • 当执行到变量声明的时候,如果变量定义了值则会被赋值。

通过 let 声明的变量拥有暂时性死区,生命周期如下:

  • 当进入 let 变量的作用域(包围它的语法块),立即为它创建(绑定)存储空间。此时变量仍是未初始化的。
  • 获取或设置未初始化的变量将抛出异常 ReferenceError
  • 当执行到变量声明的时候,如果变量定义了值则会被赋值。如果没有定义值,则赋值为 undefined

const 工作方式与 let 类似,但是定义的时候必须赋值并且不能改变。

在 TDZ 内部,如果获取或设置变量将抛出异常:

if (true) { // enter new scope, TDZ starts
    // Uninitialized binding for `tmp` is created

    tmp = 'abc'; // ReferenceError
    console.log(tmp); // ReferenceError

    let tmp; // TDZ ends, `tmp` is initialized with `undefined`
    console.log(tmp); // undefined

    tmp = 123;
    console.log(tmp); // 123
}

下面的示例将演示死区(dead zone)是真正短暂的(基于时间)和不受空间条件限制(基于位置)

if (true) { // enter new scope, TDZ starts
    const func = function () {
        console.log(myVar); // OK!
    };

    // Here we are within the TDZ and
    // accessing `myVar` would cause a `ReferenceError`

    let myVar = 3; // TDZ ends
    func(); // called outside TDZ
}

9.4.1 typeof 与暂时性死区

变量在暂时性死区无法被访问,所以无法对它使用 typeof

if (true) {
    console.log(typeof tmp); // ReferenceError
    let tmp;
}

我不认为这对大多数程序员来说是个问题:用这种方式检查变量是否存在的主要存在于库中 (特别是 polyfills)。如果你需要检查一个变量是否存在,你可以通过其他的方式(例如通过 window)。最后,从长远来看模块会减少这种类型的需求。

results matching ""

    No results matching ""