我正在寻求帮助,理解为什么我在使用匿名函数的方式在某些情况下会出错。
在下面的代码片段中,我使用了稍后调用的函数来填充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
并且因为它在该函数中没有被存储为param。创作,i
保留了它的最后一个已知值?
我真的不明白为什么我收到TypeError: arr2[c] is not a function
当我将回调函数更改为:
var func = function(i){
$("body").append(i);
};
为什么会发生这种情况,这是实现此功能的最合适/最优雅的方式。
答案 0 :(得分:0)
对于问题的第一部分,你是对的,它将保留最新的已知值。为避免这种情况,您需要使用closure。例如:
(function(x) {
arr2.push(func(x));
})(i);
关闭通常可以用作“范围黑客”。在这种情况下,它只能确保注入的值是i
的恒定电流值。
对于问题的第二部分,您的混淆可能是由于您插入函数的结果(即:func(i)
)而不是函数本身(func
)。 / p>
在第一个场景中,您返回一个显式function(){...}
,因此您的数组将包含一个可以使用运算符“()”调用的函数。
在您返回$(<...>).append()
的第二个方案中,不再保证您的返回值是函数。在这种情况下,结果是“jQuery”(参见:jQuery append)而不是函数,因此错误是正确的。您不能将该值用作函数。
唯一的出路是:
arr2.push(func);
然后:
arr2[c](c);
或者可能是这样:
(function(x){
arr2[x](x);
})(c);
如果需要,在假设正确之前始终console.log
填充数组内部的内容会很有帮助。由于Javascript不是一种打字语言,你可能会在怀疑有任何错误之前停留一段时间,因为它似乎按预期工作。
希望这有帮助!