循环内的函数
长期以来,var的特点使得循环变量在循环作用域之外仍然可被访问,于是在循环内创建函 数就变得很有问题。考虑如下代码:
var funcs = [];
for (var i = 0; i < 10; i++){
funcs.push(function(){
console.log(i);
});
}
funcs.forEach(
founction(func){
func(); //输出数值 “10” 十次
}
);
你原本可能预期这段代码会输出0到9的数值,但它却在同一行将数值10输出了十次。这是 因为变量i在循环的每次迭代中都被共享了,意味着循环内创建的那些函数都拥有对于同一 变量的引用。在循环结束后,变量i的值会是10,因此当console.log(i)被调用时, 每次都打印出10。
为了修正这个问题,开发者在循环内使用立即调用函数表达式(IIFEs),以便在每次迭代中 强制创建变量的一个新副本,示例如下:
var funcs = [];
for (var i=0; i < 10; i++){
funcs.push((function(value){
return function(){
console.log(value);
}
}(i)));
}
funcs.forEach(
function(func){
func(); // 从 0 到 9 依次输出
}
)
这种写法在循环内使用了IIFE。变量i被传递给IIFE,从而创建了value变量作为自身 副本并将值存储于其中。value变量的值被迭代中的函数所使用,因此在循环从0到9的过 程中调用每个函数都返回了预期的值。幸运的是,使用let与const的块级绑定可以在 ES6中为你简化这个循环。