关于用于防止内存泄漏的赋值为空修复的性质,有人可以为我挠痒痒吗?
我们都熟悉以下技术来阻止 DOM 对象和 JS 对象之间的循环引用,以防止内存泄漏:
function foo() {
var ele = document.getElementById("someParagraphId");
ele.onclick = function() {
//some action here
};
ele = null;
}
问题是为什么上述工作会奏效?将“ele”设置为null肯定会停止循环引用,但它不会也阻止未来对“ele”的引用吗?
function foo() {
var ele = document.getElementById("someParagraphId");
ele.onclick = function() {
console.log("accessing ele ... after set to null " + ele.onclick);
};
ele = null;
}
然而事件监听器会触发。它会抱怨“ele”对象为空(这是我们所期望的)。
鉴于上述行为,我们是否可以推断 Javascript 引擎实现将持有对事件侦听器的某种内部引用,并且在触发事件时调用的正是该引用?
eventHandlerRef = //assignment to "ele.onclick" handler/listener;
如果有像上面这样的引用,那么赋值为空的修复不是依赖于实现吗?或者,它是 ECMAScript 规范的一部分。
据我了解,此修复程序一直是跨浏览器安全的。在应用 null 分配之前,我没有遇到很多具体提到检测/嗅探浏览器类型的示例。
===============编辑==================
我认为由于我提出问题的方式,可能会在不知不觉中直接从我试图传达的内容中进行讨论。引用的几个概念:
对象句柄/对象引用 ala:
var obj1, obj2;
obj1 = {foo: "bar"}; //obj1 points to the an area of the heap allocated
//for the object literal.
obj2 = obj1; //obj2 points to the same position in the heap
//as obj1.
//obj1 = null or
obj1 = {/*another obj literal*/} //the new object literal is created
//and allocated in some other part
//in the heap, and obj1 now points
//to the new location.
//obj2 is unaffected by obj1's re-assignment.
以上不是我的痒所在,我很遗憾添加了这行:
console.log("accessing ele ... after set to null " + ele.onclick);
以上使这看起来是一个封闭的问题。我完全期望如原始帖子中所示抛出错误。
我的痒更多的是……出于某种原因,在我看来,我一直认为 Javascript 引擎会ele.onlick()
在事件触发并将元素设置为 null 时直接调用,类似于以下流程:
var obj = {};
obj.method = function() {};
obj = null;
//error calling obj.method(), i.e., obj is null
鉴于我们在原始帖子中知道事件处理程序在 ele 设置为 null 后仍会触发,因此在我看来,流程更类似于:
var obj = {};
obj.method = function() {};
var objRef = obj;
obj = null;
//The Javascript Engine calling objRef.method when event triggered.
我的痒归结为一个问题,上面是大多数 Javascript 实现是如何工作的,其中一些内部引用指向分配的事件处理程序,并且在触发事件时调用了这个内部引用?
或者换一种 说法,是什么阻止了 Javascript 引擎实现ele.onclick()
直接调用(暂时搁置设计和架构问题)?
也许我的思维过程工作方式不同,但是当他们第一次遇到 assignment-to-null 修复时,没有其他人再看一眼,其中元素引用为 null,但处理程序的代码仍然是执行?