• javascript 避免闭包引发的问题


    闭包的功能强大,但如果没有正确理解闭包的概念,其结果往往出乎人的意料。例如,下面是一个较常见的问题
     
     
    <div id="test"> 
    <div>第一个</div> 
    <div>第二个</div> 
    <div>第三个</div> 
    <div>第四个</div> 
    </div> 
    <script> 
    function test() 

    var els = document.getElementById("test").getElementsByTagName("div"); 
    for (var i = 0; i < els.length; i++) 

    var div = els[i]; 
    div.onclick = function() 

    alert(div.innerHTML); 
    return false; 



    test(); 
    </script> 
    无论我们点击哪个div,反馈的都是第4个div的内容。究其原因,在于每个div的点击事件都与test方法形成了闭包,且每个div的点击事件都共享同一个闭包作用域链。当事件被触发时,变量i所代表的下标已经指向第4个div。可以采用以下几种方式避免由于闭包引起的问题。 
    (1)使用this转换闭包的作用域链上下文,上例的闭包可以改写为: 
    for (var i = 0; i < els.length; i++) 

    var div = els[i]; 
    div.onclick = function() 

    alert(this.innerHTML); 
    return false; 


    当点击div的事件被触发时,查找的作用域已经是“this”所指定的上下文。尽管该事件仍然处于“test”闭包内,但由于不访问或不使用闭包的上下文环境,也就不存在由于闭包作用域内变量被引用所引发的问题。 
    (2)使点击div的事件与for循环形成闭包,而使得for循环内的变量div不被回收。如: 
    //for循环内定义闭包方法 
    for (var i = 0; i < els.length; i++) 

    var div = els[i]; 
    a(div); 
    function a(o) 

    o.onclick = function() 

    alert(o.innerHTML); 



    //for循环外定义闭包方法 
    for (var i = 0; i < els.length; i++) 

    var div = els[i]; 
    a(div); 

    function a(o) 

    o.onclick = function() 

    alert(o.innerHTML); 


    //使用匿名方法,其原理与for循环内定义类似 
    for (var i = 0; i < els.length; i++) 

    var div = els[i]; 
    (function(o) 

    o.onclick = function() 

    alert(o.innerHTML); 

    })(div); 

    通过中间方法a或者匿名方法,使for循环体与onclick事情产生闭包。 
    (3)控制变量的作用域,使点击div的事件所需变量与外层作用域无关。如: 
    for (var i = 0; i < els.length; i++) 

    (function() 

    var div = els[i]; 
    div.onclick = function() 

    alert(div.innerHTML); 

    })(); 

    内部函数自身也可能有内部函数。每次作用域链嵌套,都会增加由创建内部函数对象的执行环境所引发的新活动对象。ECMA262规范要求作用域链是临时性的,但对作用域链的长度却没有加以限制。闭包的潜规则即Function与内部定义的Function之间的相互作用域链上下文环境的关系。如果运用得当,嵌套的内部函数所拥有的潜能将超出了我们的想象力。
  • 相关阅读:
    第9章 垄断市场中的企业决策
    第8章 完全竞争市场中的企业决策
    第7章 生产产出的决策分析
    第6章 成本分析
    第5章 生产要素投入的决策分析
    C++_函数指针的内容和应用
    大数据的框架-流程梳理
    数字图像处理_基本概念
    C++_项目开发与Cmake构建工具
    终端--通信和传输协议
  • 原文地址:https://www.cnblogs.com/architects/p/4275127.html
Copyright © 2020-2023  润新知