for (let i = 0; i < 10; i++) {
setTimeout(function() { console.log(i) }, 0);
}
输出0-9
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i) }, 0);
}
输出10个10
在sugmentfault 的文章上看到,为什么var 改 let 输出0-9
for (let i = 0; i < 10; i++) {
setTimeout(function() { console.log(i) }, 0);
}
输出0-9
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i) }, 0);
}
输出10个10
在sugmentfault 的文章上看到,为什么var 改 let 输出0-9
10 回答11.3k 阅读
5 回答4.9k 阅读✓ 已解决
4 回答3.2k 阅读✓ 已解决
2 回答2.8k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
这是 JS 作用域的问题。
var
申明的变量,作用域是函数作用域,因为作用域链的关系,虽然外部函数执行结束,但内部函数仍然保持着对外部函数变量的引用
。注意这里是引用。因此,在下面的代码中,外部for
循环结束后,i
的值是10
。而内部函数因为setTimeout
的关系,在for
循环结束后执行,此时,10 个内部函数引用的外部函数的i
已经变成了10
,所以就打印了 10 个 10。函数作用域链的问题也是闭包问题产生的原因。而 ES6 (ES2015) 中,用
let
申明的变量,作用域是块级作用域(在此之前 js 应该是没有块级作用域的概念的)。在下面这个for
循环中,每次循环,都会生成一个块级作用域,每个块级作用域的i
都是相互独立的。相当于将某个循环时,i
的值赋
给了内部函数,注意这里是赋值,类似函数的参数传递。当内部函数执行时,i
就是循环当时i
的值。let
也是闭包问题解决的一个办法。传统的解决办法是使用参数传递,或者bind
这样的方式。