Skip to content

Instantly share code, notes, and snippets.

@Fedomn

Fedomn/TDZ.md Secret

Last active May 11, 2017 02:32
Show Gist options
  • Save Fedomn/9aa825c3fb93dc1a7a2f3daa723cfae2 to your computer and use it in GitHub Desktop.
Save Fedomn/9aa825c3fb93dc1a7a2f3daa723cfae2 to your computer and use it in GitHub Desktop.
Temporal Dead Zone

深入理解js变量声明提升

console.log(a) //undefined
var a = 1

ES5中var变量声明会提升,而ES6中let呢

var a = 1;
(function(){
  console.log(a) //ReferenceError: a is not defined
  let a = 2
})()

看出let声明变量会提升 那么var和let区别呢,他们的初始化行为不一样。var声明的变量初始化为undefined,let声明的变量会保持为未初始化(uninitialized)的状态

TDZ(Temporal Dead Zone)

它是变量被声明和被初始化之间的这段时间

var a = a // ok,分2步。1:var声明a并初始化为undefined,2:将undefined赋值给a
let b = b //ReferenceError。1:let声明b并保持uninitialize。2:获取b的值并赋值给b,而此时b为初始化。所以抛错

测试

var x=1;
function foo(x = x) {
  console.log(x)
}
foo()//ReferenceError: x is not defined

让我们分析原因,首先不要被第一行的x干扰了,应为foo函数参数里又声明了一个x, 也就说x此时又被声明了一次,用的let声明。 好的,运行到这里就和let b = b情况一样了,x状态为uninitialized,而要去获取x的值赋给x,当然会抛错。

注意

let和var 在 for的循环中会有很大不同。

for (var i = 0; i < 5; ++i) {
  // Actually prints out "5" 5 times.
  // But if you use `let` above, it'll print out 0-4
  setTimeout(() => console.log(i), 0);
}

形如for (let x...)的循环在每次迭代时都为x创建新的绑定。

这是一个非常微妙的区别,如果一个for (let...)循环执行多次并且循环保持了一个闭包,那么每个闭包将捕捉一个循环变量的不同值作为副本,而不是所有闭包都捕捉循环变量的同一个值。

这种情况适用于现有的三种循环方式:for-of、for-in、以及传统的用分号分隔的类C循环。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment