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一次就产生一个函数实例
        }

    }

  • 相关阅读:
    大段程序注释C#、lisp
    AutoCAD VBA调用lisp
    团队作业(二):需求分析 Besti2019
    团队作业(三):确定分工 Besti2019
    [电子公文传输系统团队项目]团队作业(一) Besti2019
    2.4 OpenEuler中C语言中的函数调用测试
    团队作业(四):描述设计 Besti2019
    Web服务器1socket编程
    实验四 Web服务器2
    2017清华机试题——多项式求和(polynomial)
  • 原文地址:https://www.cnblogs.com/jshen/p/3161245.html
Copyright © 2011-2022 走看看