Javascript:在 For 循环中创建函数

2024-05-07

最近,我发现自己需要创建一系列函数。这些函数使用 XML 文档中的值,并且我使用 for 循环运行适当的节点。然而,在执行此操作时,我发现数组中的所有函数仅使用过 XML 表的最后一个节点(对应于 for 循环的最后一次运行)。

以下是展示这一点的示例:

var numArr = [];
var funArr = [];
for(var i = 0; i < 10; ++i){
    numArr[numArr.length] = i;
    funArr[funArr.length] = function(){  return i; };
}

window.alert("Num: " + numArr[5] + "\nFun: " + funArr[5]());

输出为 Num: 5 和 Fun: 10。

经过研究,我发现了一个一段有效的代码 https://stackoverflow.com/questions/10813773/function-not-executed-when-creating-objects-in-a-loop-javascript,但我很难准确理解它为何有效。我用我的例子在这里复制了它:

var funArr2 = [];
for(var i = 0; i < 10; ++i)
    funArr2[funArr2.length] = (function(i){ return function(){ return i;}})(i);

window.alert("Fun 2: " + funArr2[5]());

我知道这与范围界定有关,但乍一看,它的表现似乎与我天真的方法没有任何不同。我是 Javascript 的初学者,所以如果我可能会问,为什么使用这种函数返回函数技术可以绕过范围问题?另外,为什么最后要包含(i)?

预先非常感谢您。


如果您使用不屏蔽循环变量名称的参数名称,则第二种方法会更清晰一些:

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; };
}

有了这个小小的改变,每个人funArrelement 是一个闭包绑定做一个不同的 i每次循环迭代时的对象。欲了解更多信息let, see 这篇 2015 年 Mozilla Hacks 帖子 https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/。 (如果您的目标环境不支持let,坚持我之前写的内容,或者在使用之前通过转译器最后运行它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript:在 For 循环中创建函数 的相关文章

随机推荐