请解释JavaScript闭包在循环中的使用 [英] Please explain the use of JavaScript closures in loops

查看:114
本文介绍了请解释JavaScript闭包在循环中的使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了许多关于闭包和闭包的循环中的解释。我很难理解这个概念。我有这样的代码:有一种方法来尽可能减少代码,所以封闭的概念可以做得更清楚。我很难理解 i 在两个括号内的部分。感谢

I have read a number of explanations about closures and closures inside loops. I have a hard time understanding the concept. I have this code: Is there a way to reduce the code as much as possible so the concept of closure can be made clearer. I am having a hard time understanding the part in which the i is inside two parenthesis. Thanks

function addLinks () {
    for (var i=0, link; i<5; i++) {

        link = document.createElement("a");
        link.innerHTML = "Link " + i;


        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);

    }
}
window.onload = addLinks;


推荐答案

/ strong>

WARNING: Long(ish) Answer

这是直接从我在内部公司wiki中写的文章复制的:

问题:如何正确使用闭包在循环?
快速回答:使用函数工厂。

Question: How to properly use closures in loops? Quick answer: Use a function factory.

  for (var i=0;i<10;i++) {
    document.getElementById(i).onclick = (function(x){
      return function(){
        alert(x);
      }
    })(i);
  }

或更容易阅读的版本:

  function generateMyHandler (x) {
    return function(){
      alert(x);
    }
  }

  for (var i=0;i<10;i++) {
    document.getElementById(i).onclick = generateMyHandler(i);
  }

这通常会让那些刚接触javascript或函数式编程的人感到困惑。这是误解了什么是闭包的结果。

This often confuse people who are new to javascript or functional programming. It is a result of misunderstanding what closures are.

闭包不仅仅传递一个变量的值,甚至是一个对变量的引用。闭包捕获变量本身!下面的代码段说明了这一点:

A closure does not merely pass the value of a variable or even a reference to the variable. A closure captures the variable itself! The following bit of code illustrates this:

  var message = 'Hello!';
  document.getElementById('foo').onclick = function(){alert(message)};
  message = 'Goodbye!';

单击元素'foo'将生成一个警告框,并显示以下消息:Goodbye!因此,在一个循环中使用一个简单的闭包将最终得到所有闭包共享相同的变量,该变量将包含在循环中分配给它的最后一个值。例如:

Clicking the element 'foo' will generate an alert box with the message: "Goodbye!". Because of this, using a simple closure in a loop will end up with all closures sharing the same variable and that variable will contain the last value assigned to it in the loop. For example:

  for (var i=0;i<10;i++) {
    document.getElementById('something'+i).onclick = function(){alert(i)};
  }

点击时所有元素将生成一个数字9的警告框。 ,如果我们现在 i =hello; 所有元素现在将生成一个hello警报!变量i共享十个函数PLUS当前函数/范围/上下文。把它想象成一种私有的全局变量,只有所涉及的函数可以看到。

All elements when clicked will generate an alert box with the number 9. In fact, if we now do i="hello"; all elements will now generate a "hello" alert! The variable i is shared accross ten functions PLUS the current function/scope/context. Think of it as a sort of private global variable that only the functions involved can see.

我们想要的是一个变量的实例或至少一个简单的引用变量而不是变量本身。幸运的是,javascript已经有一个传递引用(对象)或值(对于字符串和数字)的机制:function arguments!

What we want is an instance of that variable or at least a simple reference to the variable instead of the variable itself. Fortunately javascript already has a mechanism for passing a reference (for objects) or value (for strings and numbers): function arguments!

如果它是一个对象,则通过引用传递该函数,如果它是一个字符串或数字,则通过值传递。

When a function is called in javascript the arguments to that function is passed by reference if it is an object or by value if it is a string or number. This is enough to break variable sharing in closures.

这样:

  for (var i=0;i<10;i++) {
    document.getElementById(i).onclick =
      (function(x){ /* we use this function expression simply as a factory
                       to return the function we really want to use: */

        /* we want to return a function reference
           so we write a function expression*/
        return function(){
          alert(x); /* x here refers to the argument of the factory function
                       captured by the 'inner' closure */
        }

      /* The brace operators (..) evaluates an expression, in this case this
         function expression which yields a function reference. */

      })(i) /* The function reference generated is then immediately called()
               where the variable i is passed */
  }

这篇关于请解释JavaScript闭包在循环中的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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