zoukankan      html  css  js  c++  java
  • js闭包问题

    有个网友问了个问题,如下的html,为什么每次输出都是5

    <html >
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>闭包演示</title>
    <style type="text/css">
    </style>
    <script type="text/javascript">
    function init() {       // 闭包lv1
        var pAry = document.getElementsByTagName("p");
        for( var i=0; i<pAry.length; i++ ) {
             pAry[i].onclick = function() {       // 闭包lv2
             alert(i);
        }
      }
    }
    </script>
    </head>
    <body onload="init();">
    <p>产品一</p>
    <p>产品一</p>
    <p>产品一</p>
    <p>产品一</p>
    <p>产品一</p>
    </body>
    </html>

    原因:尽管是多个实例,但它们仍然共享一个外层函数闭包(lv1)中的i值,所以取决于最后一个i的值5。
    解决方式有很多,
    1、将变量 i 保存给在每个段落对象(p)上
    function init() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
         pAry[i].i = i;
         pAry[i].onclick = function() {
            alert(this.i);
         }
      }
    }

    2、将变量 i 保存在匿名函数自身
    function init2() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {  
       (pAry[i].onclick = function() {
            alert(arguments.callee.i);
        }).i = i;
      }
    }
    3、加一层闭包,i以函数参数形式传递给内层函数
    function init3() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
       (function(arg){    
           pAry[i].onclick = function() {    
              alert(arg);
           };
       })(i);//调用时参数
      }
    }

    4、加一层闭包,i以局部变量形式传递给内存函数
    function init4() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {  
        (function () {
          var temp = i;//调用时局部变量
          pAry[i].onclick = function() {  
            alert(temp);  
          }
        })();
      }
    }

    5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
    function init5() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {  
       pAry[i].onclick = function(arg) {       // 闭包lv3
           return function() {       // 闭包lv4
           alert(arg);
         }
       }(i);
      }
    }

    由于闭包lv4引用了闭包lv3中的入口参数,因此两个闭包存在了关联关系。在pAry[i]的方法未被清除之前,两个闭包都不会被销毁,但lv3为lv4保存了一个可供访问的arg值,从而达到目的。

    6、用Function实现,实际上每产生一个函数实例就会产生一个闭包
    function init6() {
        var pAry = document.getElementsByTagName("p");
           for( var i=0; i<pAry.length; i++ ) {  
            pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例
        }

    }

  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/jshen/p/3161245.html
Copyright © 2011-2022 走看看