JavaScript内存泄漏:为什么将对象分配为null起作用?

| 有人可以就用于防止内存泄漏的“空分配”修复的性质为我痒痒吗? 我们都熟悉以下技术,以停止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 \”对象为null(这是我们期望的)。 鉴于上述行为,我们是否应该推断出Javascript引擎实现将保留对事件侦听器的某种内部引用,并且触发事件时将调用该引用?
eventHandlerRef = //assignment to \"ele.onclick\" handler/listener;
如果有像上面这样的引用,那么null赋值修正是否会依赖于实现?还是它是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 Engine实现直接调用
ele.onclick()
(暂时搁置设计和体系结构问题)? 也许我的思维过程有所不同,但是当其他人第一次遇到空值赋值修复时,没有其他人再看一眼,其中元素引用为空,而处理程序的代码仍然被执行?     
已邀请:
        破坏所有旧答案,并解决编辑问题:) 让我们举一个简单的例子:
textContent
var ele = document.getElementById(\'foo\');
ele.textContent = \'abc\';
ele = null;
此代码将“ 12”的“ 9”设置为“ 13”,并丢弃对“ 14”的引用。现在,如果我再要求12英镑会怎样?...
var ele = document.getElementById(\'foo\');
ele.textContent = \'abc\';
ele = null;
ele = document.getElementById(\'foo\');
console.log(\'#foo is \' + ele.textContent);
它将记录log17ѭ。这只是表明
#foo
仍然存在于我的脚本之外,而to19 to保留了对它的引用(因为我在back19ѭ上调用了方法)。它与事件处理程序的工作原理相同。
var ele = document.getElementById(\'foo\');
ele.onclick = function() { console.log(\'abc\'); };
ele = null;
ele = document.getElementById(\'foo\');
console.log(\'#foo.onclick is \' + ele.onclick);
事件处理程序不是一种特殊的属性。它们只是您在其上写引用(对函数)的变量。这些是大致的功能语言功能,其中功能可以用作简单值。 JavaScript实现只是从DOM引用而不是
ele
引用中调用事件处理程序。让我们再举一个简单的例子,不用
document.getElementById
var a = {};
var b = a;
b.foo = function() { console.log(\"hello world!\"); };
console.log(a.foo + \" is the same as \" + b.foo);
b = null;
console.log(\"Even though b is \" + b + \", a.foo is still \" + a.foo);
a.foo();
如您所见,函数并不与我们为其分配功能的引用绑定:它们与引用指向的对象绑定。您可以从对对象的任何引用中调用它们,而不仅仅是从您用来分配函数的对象中调用。 这样,您可以使引用无效以打破循环依赖关系,而不会影响对象的正确行为。     
        由于首先通过调用
document.getElementById(\"someParagraphId\")
得到
ele
,因此在分配
ele
之前,其引用的对象已存在于内存中。它是文档的一部分-当然,除了is14ѭ之外,在内存中还有对其的引用。     
我离JavaScript专家很远。但是我想我至少可以通过提醒变量和对象之间的区别来部分回答您的问题。让我们一次一步地完成代码。
var ele = document.getElementById(\"someParagraphId\");
在这里,我们正在做两件事: 声明变量(
ele
) 将对DOM元素(对象)的引用分配给该变量 下一个:
ele.onclick = function() {
    console.log(\"accessing ele ... after set to null \" + ele.onclick);
};
在这里,我们使用变量“ 14”将回调函数分配给对象所引用的对象(同样是DOM元素)的“ 33”事件。 最后:
ele = null;
最后,我们给变量“ 14”分配一个“ 35”引用。它不再引用刚才的对象。但是,那个对象仍然在那里,带有相同的
onclick
处理程序。它没有改变。 处理程序仍被调用的事实是正确的行为。现在,对于错误,让我们再看一下分配给该DOM元素的
onclick
事件的函数:
console.log(\"accessing ele ... after set to null \" + ele.onclick);
ele
与我们刚刚分配
null
的变量非常相同。因此,当调用此函数时-再次,因为附加到该对象的“ 33”处理程序没有消失-会引发空引用异常。     

要回复问题请先登录注册