匿名函数作为回调

Anonymous function as callback

我正在寻求帮助以了解为什么我使用匿名函数的方式在某些情况下会出错。

在下面的代码片段中,我使用稍后调用的函数填充了 2 个数组。

var arr1 = [];
var arr2 = [];

// callback function
var func = function(i){
    return function(){$("body").append(i);}
};

var i = 1;
while(i <= 5)
{
    arr1.push(function(){$("body").append(i);});
    arr2.push(func(i));
  i++;
}

// invoke functions
$("body").append("Output from arr1 == ");
for(var c = 0; c < arr1.length; c++){ arr1[c](); }
$("body").append("<br> Output from arr2 == ");
for(var c = 0; c < arr1.length; c++){ arr2[c](); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

现在,我想我明白了为什么 arr1 输出 66666,因为在调用时,i == 6 并且因为它没有作为参数存储在该函数中创建时间,i 保留其最后已知值?

真的不明白的是为什么我收到TypeError: arr2[c] is not a function当我将回调函数更改为:

var func = function(i){
    $("body").append(i);
};

为什么会发生这种情况,这是实现此功能的最合适/最优雅的方式吗?

对于问题的第一部分,你是对的,它将保留最新的已知值。为避免这种情况,您需要使用 closure。例如:

(function(x) {
   arr2.push(func(x));
})(i);

闭包通常可以用作"scope hack"。这样的话,只会保证注入的值为i.

的恒流值

对于问题的第二部分,你的困惑可能是因为你插入了函数的结果(即:func(i))而不是函数本身(func) .

在第一种情况下,您 return 显式 function(){...} 因此您的数组将包含一个可以使用运算符“()”调用的函数。

在第二种情况下,您 return $(<...>).append(),不再保证您的 return 值是一个函数。在这种情况下,结果是 "jQuery"(参见:jQuery append)而不是函数,因此错误是正确的。您不能将该值用作函数。

一个出路是:

arr2.push(func);

然后:

arr2[c](c);

或者可能是这样的:

(function(x){
    arr2[x](x);
})(c);

如果需要,在假设正确之前总是 console.log 数组中填充的内容会很有帮助。由于 Javascript 不是一种类型化的语言,你可能会在怀疑任何错误之前花点时间,因为它看起来 按预期工作

希望对您有所帮助!