关于 dom清空的内存泄漏问题

先看看下面的代码

<!DOCTYPE html>  
<html>  
<head lang="en">  
  <meta charset="UTF-8">
  <title>dom empty memory leaks</title>
  <script src="http://cdn.staticfile.org/zepto/1.0rc1/zepto.min.js"></script>
  <script>
    function Memory(leaks){
      this.leaks = leaks;
    }
    function addDom(){
      var node = $('<div>');
      node.text('233333');

      var memory = new Memory('leaks');
      node.bind('click', function(){
        console.log(memory);
      });
      $('#container').append(node);
    }
    function empty(){
      var con = $('#container');
      //con.find('*').off();
      con.empty();
    }
  </script>
</head>  
<body>  
<button onclick="addDom()">add dom</button>  
<button onclick="empty()">empty dom</button>  
<div id="container">

</div>  
</body>  
</html>  
  • 按照我们的预期,当我们对点击 empty dom按钮的时候,contaner里面的 dom以及click 事件里面的 memory也应该被删除

    • 而试试我们通过 profiles工具发现 memory还在内存里面

    zepto-summary 通过 timeline工具也可以发现 Listeners一直在涨,empty调用后也没有减少 zepto-empty

  • 这和我们的预期不符,我们来看看 zepto的源码,这和 jquery差距页太大了(jquery 中调用 empty时为了避免内存泄露,会帮你先把事件清楚掉)

empty: function(){  
    return this.each(function(){
    this.innerHTML = '' 
})}

如何修复

从上面的代码以及 jquery的源码,我们可以得出结论,移除 dom 之前,要先把 dom绑定的事件同时清楚,否则会造成内存泄露。所以上面的代码我们只需要调用删除前,加一行con.find('*').off();即可。

  • 让我们再看看,修复后的情况 profiles图,div数量减少

div

  • profiles 图,memory删除

summary-off

  • timeline 图,事件数减少(但是 Nodes没有减少,我猜测这个 Nodes不是指的 dom节点数)

timeline-off

: ) boke.io