循环中的函数(返回另一个函数)如何工作? [复制]

Posted

技术标签:

【中文标题】循环中的函数(返回另一个函数)如何工作? [复制]【英文标题】:How does a function in a loop (which returns another function) work? [duplicate] 【发布时间】:2010-12-05 21:26:47 【问题描述】:

我一直在尝试将函数分配给 javascript 中动态创建的“a”标签的 onclick 事件。所有标签都在一个循环中创建,如下所示:

for ( var i = 0; i < 4; i++ )

  var a = document.createElement( "a" );
  a.onclick = function( )  alert( i ) ;
  document.getElementById( "foo" ).appendChild( a );

所有四个链接的警报值始终为“4”。很明显。谷歌搜索时,我发现了一个显示以下代码 sn-p 的帖子:

a.onclick = (function(p, d) 
return function() show_photo(p, d) 
)(path, description);

我设法根据自己的需要对其进行了调整,并让 alert(i) 正常工作,但如果有人能准确解释上述代码的作用,我将不胜感激。

【问题讨论】:

嗨,你能告诉我为什么它会提示“4”吗?不应该是“2”吗?谢谢。 for (var i = 0; i 我的错...循环应该在 i = 0 到 3 时运行,所以它要么是 "i 【参考方案1】:

无需过多详细说明,这实质上是通过将实例变量包装在一个立即执行的函数中来创建实例变量的副本,并将其传递给单击元素时将执行的函数。

这样想:

function()  alert(i);   // Will expose the latest value of i
(function(I)  return function()  alert(I); ; )(i); // Will pass the current
                                                       // value of i and return
                                                       // a function that exposes
                                                       // i at that time

因此,在循环的每次迭代中,您实际上是在执行一个函数,该函数返回一个 functioncurrent 变量值。

如果你想象你的循环中有 4 个锚点,那么你正在创建 4 个独立的函数,这些函数可以被可视化为......

function()  alert(0); ;
function()  alert(1); ;
function()  alert(2); ;
function()  alert(3); ;

我会考虑使用 javascript 研究范围和闭包,就好像你走这条路但不知道到底发生了什么,你可能会因意外行为而遇到大量问题。

【讨论】:

感谢您的解释。这是一个很好的 hack - 或者这就是它在 javascript 中完成的方式?【参考方案2】:

当 onclick 事件被触发时,匿名函数被调用,它引用了循环中使用的同一个变量i,它保存了i 的最后一个值,即 4。

解决您的问题的方法是使用返回函数的函数:

a.onclick = (function(k) return function()  alert(k); ; )(i);

【讨论】:

【参考方案3】:

当您将函数分配给点击处理程序时,会创建一个closure。

当你嵌套函数时,基本上会形成一个闭包,即使在它们的父函数已经执行之后,内部函数也可以引用其外部封闭函数中存在的变量。

在执行 click 事件时,处理程序引用 i 变量的最后一个值,因为该变量存储在闭包中。

正如您所注意到的,通过包装 click 处理函数以接受 i 变量作为参数,并返回另一个函数(基本上是创建另一个闭包),它可以按预期工作:

for ( var i = 0; i < 4; i++ ) 
  var a = document.createElement( "a" );
  a.onclick = (function(j)  // a closure is created
    return function () 
      alert(j); 
    
  (i));
  document.getElementById( "foo" ).appendChild( a );

当你迭代时,实际上创建了4个函数,每个函数在创建时存储一个对i的引用(通过传递i),这个值存储在外部闭包上,内部函数在执行时点击事件触发。

我使用下面的sn-p来解释闭包(和curry的一个非常基本的概念),我认为一个简单的例子可以更容易理解这个概念:

// a function that generates functions to add two numbers
function addGenerator (x)  // closure that stores the first number
  return function (y) // make the addition
    return x + y;
  ;


var plusOne = addGenerator(1), // create two number adding functions
    addFive = addGenerator(5);

alert(addFive(10)); // 15
alert(plusOne(10)); // 11

【讨论】:

泰勒,我为你感到高兴,我会让你完成,但这篇文章是有史以来最好的。 难怪你有 42k 点 :) 有一天,人们会像我一样忘记 Kanye West,所有提到他的模因都会变得粗鲁和有点奇怪。

以上是关于循环中的函数(返回另一个函数)如何工作? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何将一个二维数组中的内容复制到另一个二维数组

如何调用另一个类中的函数? [复制]

从函数返回对象时调用C ++中的复制构造函数?

如何从AngularJS中的另一个控制器调用函数? [复制]

如何导航到 UWP 中的参数化构造函数? [复制]

从C中的另一个函数调用主函数