如果您使用不屏蔽循环变量名称的参数名称,则第二种方法会更清晰一些:
funArr[funArr.length] = (function(val) { return function(){ return val; }})(i);
您当前代码的问题是每个函数都是一个closure https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures并且它们都引用相同的变量i
。当每个函数运行时,它返回的值i
函数运行时(将比循环的限制值大 1)。
更清晰的方法是编写一个单独的函数来返回您想要的闭包:
var numArr = [];
var funArr = [];
for(var i = 0; i < 10; ++i){
numArr[numArr.length] = i;
funArr[funArr.length] = getFun(i);
}
function getFun(val) {
return function() { return val; };
}
请注意,这与我的答案中的第一行代码基本上执行相同的操作:调用返回函数的函数并传递值i
作为参数。它的主要优点是清晰度。
EDIT:现在几乎所有地方都支持 EcmaScript 6(对不起,IE 用户),您可以使用更简单的方法 — 使用let
关键字而不是var
对于循环变量:
var numArr = [];
var funArr = [];
for(let i = 0; i < 10; ++i){
numArr[numArr.length] = i;
funArr[funArr.length] = function(){ return i; };
}
有了这个小小的改变,每个人funArr
element 是一个闭包绑定做一个不同的 i
每次循环迭代时的对象。欲了解更多信息let
, see 这篇 2015 年 Mozilla Hacks 帖子 https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/。 (如果您的目标环境不支持let
,坚持我之前写的内容,或者在使用之前通过转译器最后运行它。