循环内的函数

长期以来,var的特点使得循环变量在循环作用域之外仍然可被访问,于是在循环内创建函 数就变得很有问题。考虑如下代码:

var funcs = [];

for (var i = 0; i < 10; i++){
    funcs.push(function(){
    console.log(i);
    });
}

funcs.forEach(
    founction(func){
        func();        //输出数值 “10” 十次
    }
);

你原本可能预期这段代码会输出09的数值,但它却在同一行将数值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变量的值被迭代中的函数所使用,因此在循环从09的过 程中调用每个函数都返回了预期的值。幸运的是,使用letconst的块级绑定可以在 ES6中为你简化这个循环。

results matching ""

    No results matching ""