Javascript:在For循环中创建函数 [英] Javascript: Creating Functions in a For Loop

查看:161
本文介绍了Javascript:在For循环中创建函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我发现自己需要创建一组函数。这些函数使用XML文档中的值,并且我正在使用for循环通过适当的节点运行。但是,这样做后,我发现只有XML表单的最后一个节点(对应于for循环的最后一次运行)曾被数组中的所有函数使用。



以下是一个示例:

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

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

输出是Num:5和Fun:10。

经研究,我发现一个可以工作的代码段,但我正在努力理解它的工作原理。我在这里使用我的例子复制它:

  var funArr2 = []; (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 ,它们都引用相同的变量 i 。当每个函数运行时,它在函数运行时返回 i 的值(这将比循环的极限值多一个)。



更清晰的方法是编写一个单独的函数,返回所需的闭包:

  var numArr = []; 
var funArr = []; (var i = 0; i <10; ++ i){
numArr [numArr.length] = i;
funArr [funArr.length] = getFun(i);


函数getFun(val){
return function(){return val; };

$ / code>

请注意,这与第一行代码基本相同我的回答是:调用一个返回一个函数并将 i 的值作为参数的函数。它的主要优点是清晰度。



编辑:现在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; };



$ b $ p
$ b

每次 funArr 元素是一个闭包绑定,在每次循环迭代中做一个不同的 i 对象。有关 let 的更多信息,请参阅此Mozilla从2015年开始的黑客帖子。 (如果你的目标环境不支持 let ,请坚持我之前写的内容,或者在使用前通过一个转译器运行。


Recently, I found myself needing to create an array of functions. The functions use values from an XML document, and I am running through the appropriate nodes with a for loop. However, upon doing this, I found that only the last node of the XML sheet (corresponding to the last run of the for loop) was ever used by all of the functions in the array.

The following is an example that showcases this:

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]());

The output is Num: 5 and Fun: 10.

Upon research, I found a a segment of code that works, but I am struggling to understand precisely why it works. I reproduced it here using my example:

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]());

I know it has to do with scoping, but at first glance it does not seem like it would perform any differently from my naive approach. I am somewhat of a beginner in Javascript, so if I may ask, why is it that using this function-returning-a-function technique bypasses the scoping issue? Also, why is the (i) included on the end?

Thank you very much in advance.

解决方案

The second method is a little clearer if you use a parameter name that does not mask the loop variable name:

funArr[funArr.length] = (function(val) { return function(){  return val; }})(i);

The problem with your current code is that each function is a closure and they all reference the same variable i. When each function is run, it returns the value of i at the time the function is run (which will be one more than the limit value for the loop).

A clearer way would be to write a separate function that returns the closure that you want:

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

Note that this is doing basically the same thing as the first line of code in my answer: calling a function that returns a function and passing the value of i as a parameter. It's main advantage is clarity.

EDIT: Now that EcmaScript 6 is supported almost everywhere (sorry, IE users), you can get by with a simpler approach—use the let keyword instead of var for the loop variable:

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

With that little change, each funArr element is a closure bound do a different i object on each loop iteration. For more info on let, see this Mozilla Hacks post from 2015. (If you're targeting environments that don't support let, stick with what I wrote earlier, or run this last through a transpiler before using.

这篇关于Javascript:在For循环中创建函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆