代码之家  ›  专栏  ›  技术社区  ›  Salman Arshad

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

  •  21
  • Salman Arshad  · 技术社区  · 15 年前

    这个问题已经有了答案:

    我一直在尝试为动态创建的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”。很明显。谷歌搜索时,我看到一个帖子,上面显示了以下代码片段:

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

    我设法根据我的需要对它进行了调整,使它能够正常工作,但如果有人能准确地解释上面的代码的作用,我将不胜感激。

    3 回复  |  直到 12 年前
        1
  •  45
  •   Salman Arshad    13 年前

    将函数分配给单击处理程序时, closure 创建。

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

    在执行click事件时,处理程序引用 i 变量有,因为该变量存储在闭包上。

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

    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个函数,每个函数存储对 在它被创造的时候 ,此值存储在外部闭包上,当触发Click事件时,将执行内部函数。

    我使用以下代码片段来解释闭包(以及 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
    
        2
  •  10
  •   Quintin Robinson    15 年前

    在不涉及太多细节的情况下,这基本上是通过将实例变量包装在一个立即执行的函数中,并将其传递回在单击元素时将执行的函数来创建实例变量的副本。

    这样想:

    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
    

    所以在循环的每次迭代中,实际上 执行 一个返回 功能 现在的 变量的值。

    如果您设想循环中有4个锚,那么您将创建4个独立的函数,这些函数可以可视化为..

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

    我会考虑使用JavaScript来研究范围和闭包,就好像您沿着这条路走,并且不确切地了解正在发生的事情,您可能会遇到意想不到的行为带来的巨大问题。

        3
  •  2
  •   Peter Mortensen icecrime    15 年前

    当触发onclick事件时,调用匿名函数并引用同一个变量 i 在循环中使用,它保存了 那是4。

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

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