搜尋

首頁  >  問答  >  主體

javascript - 为什么这段 js 代码出现内存泄露

function attachEvents() {  
    var element = document.getElementById("myID");  
    element.onclick = function() {  
        alert("Element clicked");  
    }  
};  
attachEvents(); 
ringa_leeringa_lee2896 天前903

全部回覆(5)我來回復

  • PHPz

    PHPz2017-04-10 12:49:46

    该代码创建了一个引用循环

    函数引用了 elementelement 又引用了函数。

    变量元素包含函数的引用(归于 onclick 属性)。 同时,函数保持一个 DOM 元素的引用(提示:函数内部可以访问元素,因为闭包)。

    所以 JavaScript 垃圾收集器不能清除元素或是函数,因为他们被相互引用。 大部分的 JavaScript 引擎对于清除循环应用都不够聪明。

    解决办法:避免那些闭包,或者不去做函数内的循环引用。

    function attachEvents() {
        var element = document.getElementById("myID");
        element.onclick = function() {
            //Remove element, so function can be collected by GC
            delete element;
            alert("Element clicked");
        }
    };
    attachEvents();
    

    谢谢 @沙之守护 的提醒,原文有误:delete 不能够删除变量,参见我在 sf 发表的博文 javascript 中的 delete,应该写 element = null


    TODO:明天继续更新……

    参考:http://justjavac.com/named-function-expressions-demystified.html#jscript-memory-management

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-10 12:49:46

    好久没有研究内存泄漏的课题了。姑且猜猜吧。

    attachEvents 原本是一次性执行结束的,但其中包含了一个匿名的函数——那个监听器,结果它就被这个监听器“绑架”了(不能安心地驾鹤西去)。

    而监听器又被绑定给了element对应的DOM对象。DOM对象只要还在网页中,那么就一直有效。

    但我不太清楚:

    • element变量真的没有被自动回收?它指向了DOM对象后就完成使命了啊。
    • 这种程度的“内存泄漏”有多大危害?
    • 另外,是不是所有浏览器的GC都对此束手无策?

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-10 12:49:46

    内存泄漏是closure的原因造成的。闭包是由函数和构建函数的环境所组成的。 按理说,函数运行完成后,内部变量会被销毁。但是看这段代码,attachEvent函数内部返回了click函数,构造了一个闭包,这就导致了element变量会被onclick函数所引用。因此javascript垃圾回收器并不会回收element变量。 除了element=null的方法外,还可以把函数写在外面来避免。

    function attachEvent() 
    { 
        var obj = document.getElementById("XXX"); 
        obj.onclick=onclickHandler; 
    } 
    function onclickHandler(){ 
        //do something 
    }
    

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-10 12:49:46

    这段代码会引起内存泄露啊。。。。我经常这么做。。。。晕了!

    回覆
    0
  • 阿神

    阿神2017-04-10 12:49:46

    这个研究方向不错,很支持。JS高手可以来我找兼职

    回覆
    0
  • 取消回覆