typeof 和暂时性死区的执行分析

分析函数调用中 typeof 操作符和 let 声明的暂时性死区问题

问题

分析以下代码的执行结果:

foo(typeof a);
function foo(p) {
  console.log(this);
  console.log(p);
  console.log(typeof b);
  let b = 0;
}

解答

这段代码会抛出错误,具体执行过程如下:

第一步:函数调用

foo(typeof a) 中,变量 a 未声明,但 typeof 对未声明变量不会报错,返回 "undefined"

第二步:函数内部执行

console.log(this);  // Window(非严格模式下全局调用)
console.log(p);     // "undefined"
console.log(typeof b);  // ReferenceError

第三行会抛出错误:ReferenceError: Cannot access 'b' before initialization

原因分析

变量 b 使用 let 声明,在声明之前访问会触发暂时性死区(TDZ)。与 var 不同,let 声明的变量不会被提升为 undefined,在声明语句之前的区域都是死区。

实际输出

Window
"undefined"
ReferenceError: Cannot access 'b' before initialization

关键点

  • typeof 对未声明变量返回 "undefined",不会报错
  • 非严格模式下全局调用函数,this 指向全局对象(浏览器中是 window
  • letconst 声明的变量存在暂时性死区,在声明前访问会抛出 ReferenceError
  • 暂时性死区从块级作用域开始到变量声明语句之间,即使使用 typeof 也无法避免