为什么会出现内存泄漏问题?

3

大家好,

我想知道为什么这是内存泄漏:

window.onload = function outerFunction(){
    var obj = document.getElementById("app")
    obj.onClick = function innerFunction(){
        alert("Hi, I will leak");
    }
}


<button id="app">Click Me</button>

这个例子的意思是:一个 JavaScript 对象(obj)包含对 DOM 对象(由 id “app” 引用)的引用。DOM 元素反过来又引用 JavaScript obj,这导致 JavaScript 对象和 DOM 对象之间产生循环引用,从而造成内存泄漏。
解决方法是:在 function outerFunction 的末尾,将 obj = null
我的疑惑是:
为什么它说 DOM 有对那个 obj 的引用?我无法理解这一点。为什么这会导致内存泄漏?

6
你从哪里得到这个例子? - RaminS
1
可能相关:JavaScript 闭包中的内存泄漏风险 - Felix Kling
1
泄漏问题在于在旧版浏览器中,即使obj不再被引用,它也无法被垃圾回收。 - Felix Kling
1
@Kuan,是的,我认为是这样的,因为它在outerFunction内部声明,它的闭包作用域将包括obj,即使你不引用它。 - jo_va
1
我会把那些信息放在回答里,这样可以吗? - jo_va
显示剩余16条评论
1个回答

3
以下文章已经过时,这不再是一个问题。
该问题在本文中描述:
window.onload = function() {
    var obj = document.getElementById("element");

    // this creates a closure over "element"
    obj.onclick = function(evt) {
        ... logic ...
    };
};

这里有一个图表描述了闭包是如何在DOM世界和JS世界之间创建循环引用的。

enter image description here

上述模式会因闭包而泄漏。在这里,闭包的全局变量obj指向DOM元素。同时,DOM元素持有对整个闭包的引用。这在DOM和JS世界之间生成了循环引用。这是泄漏的原因。
来自MDN web docs:闭包是函数和声明该函数的词法环境的组合。在这种情况下,词法环境是window.onload函数,其中包括obj变量。

2
值得一提的是,这个问题已经不再是问题了,而且这篇文章很可能非常古老:“我们应该记住,虽然它是市场领导者,但IE并不是世界上唯一的浏览器。” - Felix Kling
@FelixKling 现在这个是如何处理的? - Kuan
1
@Kuan:我认为浏览器只是更擅长检测这些依赖关系并且仍然可以垃圾回收对象。我无法详细告诉你垃圾回收的工作原理。 - Felix Kling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接