代码之家  ›  专栏  ›  技术社区  ›  nonopolarity

为什么一个JavaScript闭包可以工作而另一个不行?

  •  6
  • nonopolarity  · 技术社区  · 14 年前

    版本1:

    <a href="#" id="link1">click me</a>
    <a href="#" id="link2">click me</a>
    <a href="#" id="link3">click me</a>
    <a href="#" id="link4">click me</a>
    <a href="#" id="link5">click me</a>
    
    <script type="text/javascript">
        for (i = 1; i <= 5; i++) {
            document.getElementById('link' + i).onclick = (function() {
                return function() {
                    var n = i;
                    alert(n);
                    return false;
                }
            })();
        }
    </script>
    

    版本2:

    <a href="#" id="link1">click me</a>
    <a href="#" id="link2">click me</a>
    <a href="#" id="link3">click me</a>
    <a href="#" id="link4">click me</a>
    <a href="#" id="link5">click me</a>
    
    <script type="text/javascript">
        for (i = 1; i <= 5; i++) {
            document.getElementById('link' + i).onclick = (function() {
                var n = i;
                return function() {
                    alert(n);
                    return false;
                }
            })();
        }
    </script>
    

    版本1将不起作用。第2版将会。我想我知道原因,但我想比较一下其他人的解释,为什么版本1不起作用。

    3 回复  |  直到 13 年前
        1
  •  4
  •   Pointy    14 年前

    版本1不起作用,因为有一个公共变量“i”(a 全球的 在这种情况下是可变的,因为 var )由循环创建的每个“click”处理程序函数共享。

    在第二个版本中,使用小包装器函数创建一个新的词法作用域。这使得每个“点击”处理程序都有自己的私有“i”。

        2
  •  3
  •   fantactuka    14 年前

    n = i; 它使 i 值在onclick函数内的作用域。而在第一个函数中,onclick函数仍然使用

    我建议使用以下用法:

      for (i = 1; i <= 5; i++) {
        document.getElementById('link' + i).onclick = (function(i) {
          return function() {
            alert(i); 
            return false;
          }
        })(i);
      }
    

    将是onclick函数的局部变量,因为它是一个参数。

        3
  •  0
  •   Shoaib Nawaz    14 年前

    第一个不起作用是因为:我是每个闭包的一部分。经过5次迭代,现在我是6,因为后缀增量运算符。每次调用事件处理程序时,它都会从其闭包作用域中获取i的值,该值始终为6。

    第二部分起作用:因为每个闭包在n中复制i,n是每个闭包的一部分。