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的变量。你可以将匿名函数的参数名变成其他的就能比较理解这一点。