我明白,让我们避免重复的声明是不错的.
let x; let x; // error!
用let声明的变量也可以用在可以预期的闭包中
let i = 100; setTimeout(function () { console.log(i) },i); // '100' after 100 ms
我有一些困难抓住是如何适用于循环.这似乎是针对for循环.考虑经典问题:
// prints '10' 10 times for (var i = 0; i < 10; i++) { process.nextTick(_ => console.log(i)) } // prints '0' through '9' for (let i = 0; i < 10; i++) { process.nextTick(_ => console.log(i)) }
为什么在这种情况下使用let工作?在我的想象中,即使只有一个块是可见的,实际上为每个迭代创建一个单独的块,并且let声明在该块内部完成…但是只有一个let声明来初始化该值.这只是ES6的语法糖吗?这是如何工作的?
我了解var和let之间的区别,并在上面说明了它们.我特别感兴趣的是,为什么不同的声明导致使用for循环的不同输出.
解决方法
Is this just syntactic sugar for ES6?
不,它超过了语法糖.血腥细节埋在§13.6.3.9
CreatePerIterationEnvironment
年.
How is this working?
如果在for语句中使用let关键字,它将检查它绑定的名称,然后
>为这些名称创建一个新的词汇环境a)初始化表达式b)每次迭代(以前用于评估递增表达式)
>将所有变量的值从这些名称复制到下一个环境
你的循环语句(var i = 0; i< 10; i){process.nextTick(_ => console.log(i))}
// omitting braces when they don't introduce a block var i; i = 0; if (i < 10) process.nextTick(_ => console.log(i)) i++; if (i < 10) process.nextTick(_ => console.log(i)) i++; …
而对于(让i = 0; i <10; i){process.nextTick(_ => console.log(i))}对于更复杂的“desugar”
// using braces to explicitly denote block scopes,// using indentation for control flow { let i; i = 0; __status = {i}; } { let {i} = __status; if (i < 10) process.nextTick(_ => console.log(i)) __status = {i}; } { let {i} = __status; i++; if (i < 10) process.nextTick(_ => console.log(i)) __status = {i}; } { let {i} = __status; i++; …