js学习笔记“暂时性死区”

209 阅读2分钟
  • 只要块级作用域内存在let命令,它所声明的变量就“绑定”(bind)在这个区域。不再受外部影响。
  • 例如:
var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}
  • 上述代码运行会报错;什么原因呢?
  • 代码中if代码块外部全局声明了变量tmp;if代码块内使用let命令声明了变量tmp,那么此变量tmp就绑定在了这个代码块内,所以在let命令声明变量之前,对变量tmp赋值(tmp = 'abc')运行代码会报错。
  • ES6规定:如果区块内存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭式作用域。如果在声明之前使用这些变量就会报错。总之;在区块内使用let命令声明变量前,改变量是不能被使用的,这在语法上成为**“暂时性死区”**。
  • 注意let命令不允许在相同的作用域内重复声明同一个变量
if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}
  • 上述代码也是一样,let命令声明变量之前,对变量赋值都属于错误。因此这就要求我们写代码时要养成好的习惯。
  • 有些死区比较隐蔽,容易被忽略
  • 例如:
function bar(x = y, y = 2) {
  return [x, y];
}
bar(); // 报错
  • 上面代码中,调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了。
function bar(x = 2, y = x) {
  return [x, y];
}
bar(); // [2, 2]

  • ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。

  • 总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。