var printActions = new Array(); for(var i = 0; i < 10; i++) { printActions.push(function() { console.log(i); }); } for(var i = 0; i < printActions.length; i++) { printActions[i](); }
上面的代码执行的结果,相信了解java中的闭包的同学就知道是:
10
10
10
10
10
10
10
10
10
10
但是答案是:
0
1
2
3
4
5
6
7
8
9
这是为什么呢?
因为在第二个循环中i的值又被覆盖了。也就是说,javascript的变量求值是惰性的,只是根据变量名而在当前的context中求值。
for(var j = 0; j < printActions.length; j++) { printActions[j](); }
这样子就看到10个10了。
为了避免这样的问题,我们应该"保护现场",javascript中的一个惯用做法是:
for(var i = 0; i < 10; i++) { (function(i) { printActions.push(function() { console.log(i); }); })(i); }
这里的console.log(i)的i事实上已经是被求值了的,而不是一个依赖于context的变量。你可以将匿名函数的参数名变成其他的就能比较理解这一点。