在最近的一次采访中,有人问我:“像这段代码一样,在引用 DOM 元素时使用闭包有什么危险?”
var firstNameValue = (function(elementId) {
var firstName = document.getElementById(elementId);
return firstName.value;
})("firstName");
显然,我不知道的是,上面的代码在 IE 中造成了内存泄漏。给定的基本原理相当模糊,我不明白,但显然这可能只适用于较旧的 IE 版本?
谁能详细说明一下吗?
请您参考如下方法:
IE 内部用于处理 DOM 分配的内存的垃圾收集器不知道如何释放可能由 JScript 引擎分配的悬空内存。因此,它只是忽略这些事情。
因此,您将事件处理程序绑定(bind)到 DOM 元素(或类似的东西),并且您的事件处理程序是在某个其他函数的调用中创建的函数,并且该其他函数有一个本地数组,其中包含十亿个内容好吧,在 DOM 元素本身被垃圾化之后很长一段时间,甚至在包含它的页面被释放之后很长一段时间(我认为;已经有一段时间了),这十亿个东西仍然存在。 p>
function bindHandler(domElement) {
var hoHumWhatever = generateGiganticObjectNow();
domElement.onclick = function() {
alert("oww you clicked me");
};
}
现在“hoHumWhatever”变量已保存在闭包中。当重新加载页面或修改 DOM 导致元素被丢弃时,DOM 垃圾收集器将无法对指向 JScript 拥有的内存的属性执行任何操作。另一方面,JScript 不知道 DOM 节点已被释放,因此它认为闭包内存仍然被引用。
我承认这在某些细节上可能不准确,但这是基本问题。很多人都写过关于此的文章,包括 Crockford 先生和(我认为)quirksmode 的 ppk。
编辑 - 更仔细地重新阅读您发布的代码,我认为可能是类似但相反情况的一个示例: Little 函数返回对 DOM 值的一部分的引用,因此也许有人会说 JScript 将卡在 DOM 内存上(而不是反之亦然)。现在,在这种特殊情况下,我有点怀疑,因为除了对 DOM 属性的简单引用之外,我看不出有什么东西是如何从该闭包中“逃脱”的,该属性应该是一个原始字符串实例,因此实际上应该是这样的不会造成问题。然而这些事情可能具有欺骗性,所以我就坐在这里挠头。