选自 Typescript 中文教程。
快速的猜一下下面的代码会返回什么:
for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 100 * i); }
好吧,看一下结果:
10 10 10 10 10 10 10 10 10 10
我们传给setTimeout
的每一个函数表达式实际上都引用了相同作用域里的同一个i
。
让我们花点时间思考一下这是为什么。 setTimeout
在若干毫秒后执行一个函数,并且是在for
循环结束后。for
循环结束后,i
的值为10
。 所以当函数被调用的时候,它会打印出 10
!
而 let(ES6中声明变量的关键字) 则不会这样。
回想一下前面setTimeout
的例子,我们最后需要使用立即执行的函数表达式来获取每次for
循环迭代里的状态。 实际上,我们做的是为获取到的变量创建了一个新的变量环境。
当let
声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境,而是针对 每次迭代都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事,所以在 setTimeout
例子里我们仅使用let
声明就可以了。
for (let i = 0; i < 10 ; i++) { setTimeout(function() {console.log(i); }, 100 * i); }
会输出与预料一致的结果:
0 1 2 3 4 5 6 7 8 9