当前位置: 首页 > 面试题库 >

请解释循环中JavaScript闭包的用法

邢飞昂
2023-03-14
问题内容

我已经阅读了许多有关闭包和循环内闭包的解释。我很难理解这个概念。我有以下代码:有没有办法尽可能减少代码,以便可以使闭包的概念更清晰。我很难理解其中i两个括号内的部分。谢谢

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;

问题答案:

警告:长(ish)答案

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

问题:如何在循环中正确使用闭包?快速解答:使用功能工厂。

  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或函数式编程的人感到困惑。这是误解什么是闭包的结果。

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

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

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

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

单击所有元素都会生成一个数字为10的警报框。实际上,如果我们现在执行i="hello";所有操作,那么所有元素现在都将生成一个“
hello”警报!变量i在十​​个函数加上当前函数/作用域/上下文之间共享。可以将其视为只有相关函数才能看到的一种私有全局变量

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

在javascript中调用函数时,如果该函数是对象,则通过引用传递该函数的参数;如果是字符串或数字,则按值传递该函数的参数。这足以破坏闭包中的变量共享。

所以:

  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 */
  }


 类似资料:
  • 本文向大家介绍详解Python循环作用域与闭包,包括了详解Python循环作用域与闭包的使用技巧和注意事项,需要的朋友参考一下 前言 首先来看一段代码 这段代码会输出什么呢? 正确答案是一个长度为29的List。 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26

  • 问题内容: 目前,我正在执行在循环内执行闭包的代码。我想知道所有闭包何时完成执行。目前,我正在使用一个计数器,并在关闭完成时将其递增,然后将其与要执行的时间进行比较。代码如下 有没有计数器的更好的方法。谢谢。 问题答案: 您可以为此使用。它的工作就像计数信号灯一样。您可以通过调用来增加计数,并通过来减少计数。您可以使用以下命令安排闭包在计数达到0时执行:

  • 本文向大家介绍javascript闭包的理解,包括了javascript闭包的理解的使用技巧和注意事项,需要的朋友参考一下 1、首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量。没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部变量,注意在函数内部定义变量时一定要使用var关键字,不带var关键字的变量为全局变量。 javascript中每一段代码都有与之关联的作用域

  • 本文向大家介绍Javascript的闭包详解,包括了Javascript的闭包详解的使用技巧和注意事项,需要的朋友参考一下 前言:还是一篇入门文章。Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读

  • 问题内容: Go编译器不应该将循环变量捕获为本地分配的闭包变量吗? 长版: 这也引起了我对C#的困惑,并且我试图理解它。这就是为什么它在C#5.0中已得到修复(原因:循环变量 不能 在循环体内改变)以及未在C#循环中对其进行修复的原因(原因:循环变量 可以 在循环体内改变)。 现在(对我而言),Go中的循环看起来很像C#中的循环,但是尽管事实是我们无法更改这些变量(例如和中)。仍然我们必须首先将它

  • 问题内容: 我使用jQuery发送AJAX请求,从服务器检索数据。 然后将该数据附加到元素。这应该发生5次,但总是会随机发生3、4或5次。基本上,循环有时会跳过AJAX请求,但大多数情况下都会捕获该请求。如何确保每次完成五次请求?以及跳过AJAX请求的这种随机行为的背后原因是什么?(旁注。我已经检查了请求错误,但从未警告到请求失败) 这是我的JS: ps这发生在按下按钮时。 问题答案: 不要同步进