JavaScript内存泄漏说明

时间:2012-02-09 08:56:18

标签: javascript browser

function addHandler() {  
    var el = document.getElementById('el');  
    el.onclick = function() {  
        this.style.backgroundColor = 'red';  
    }  
}

上面的代码包含在Mozilla blog post on JavaScript中,并声明上述代码会导致内存泄漏。

有人可以解释一下:

  

因为对匿名内部函数创建的闭包无意中捕获了对el的引用。这将在JavaScript对象(函数)和本机对象(el)之间创建循环引用。

谢谢!

3 个答案:

答案 0 :(得分:2)

根据我的解释,这不是一个记忆泄漏本身(有时你不能解决你的问题没有像这样的结构,但它们要复杂得多),但它并不好,因为你创建了onclick函数每次都是新的,它保持与其父级的“链接”(闭包的作用)。这段代码会好得多;

function clickHandler(){
    this.style.backgroundColor = 'red';
}
function addHandler() {  
    var el = document.getElementById('el');  
    el.onclick = clickHandler           
}

这样,就不会创建闭包,也不会产生任何未使用的引用,也不会多次生成任何函数。

答案 1 :(得分:1)

@ thg435:看起来这可能是使用eval的结果。

foo上使用手表在Firefox或Chrome中执行以下操作,同时在debugger处将foo的值报告为未定义。

(function () {
  var foo = "bar";
  return function() {
    debugger;
  };
})()();

执行以下报告时foo的值为"bar",同时在debugger处断开:

(function () {
  var foo = "bar";
  return function(_var) {
    debugger;
    return eval(_var);
  };
})()('foo');

很高兴得到一个明确的答案。

答案 2 :(得分:0)

问题是:闭包是捕获当前作用域中的所有变量还是仅捕获那些明确提到的变量?考虑:

function makeClosure() {
   var foo = 1;
   var bar = ...some heavy object...

   return function() {
       do_something_with(foo)
   }
}

内部函数捕获foo,它是否也捕获bar?我想,是的,因为以下内容打印了正确的值:

function makeClosure(bar) {
   var foo = 1;

   return function(name) {
       console.log(foo);
       console.log(eval(name));

   }
}

makeClosure('print_me')('bar')

因此,在您的示例中,el在闭包中被“无意中”捕获(onclick处理程序)。因此,闭包是指el,而el.onclick指的是闭包,qed。