| 
                         该对象包含四个字段,单位是字节,含义如下: 
    - rss(resident set size):所有内存占用,包括指令区和堆栈。
 
    - heapTotal:"堆"占用的内存,包括用到的和没用到的。
 
    - heapUsed:用到的堆的部分。
 
    - external: V8 引擎内部的 C++ 对象占用的内存。
 
 
判断内存泄漏,以heapUsed字段为准。 
常见的内存泄露案例 
意外的全局变量 
- function foo() { 
 -  bar1 = 'some text'; // 没有声明变量 实际上是全局变量 => window.bar1 
 -  this.bar2 = 'some text' // 全局变量 => window.bar2 
 - } 
 - foo(); 
 
  
在这个例子中,意外的创建了两个全局变量 bar1 和 bar2 
被遗忘的定时器和回调函数 
在很多库中, 如果使用了观察者模式, 都会提供回调方法, 来调用一些回调函数。 
要记得回收这些回调函数。举一个 setInterval的例子: 
- var serverData = loadData(); 
 - setInterval(function() { 
 -  var renderer = document.getElementById('renderer'); 
 -  if(renderer) { 
 -  renderer.innerHTML = JSON.stringify(serverData); 
 -  } 
 - }, 5000); // 每 5 秒调用一次 
 
  
如果后续 renderer 元素被移除,整个定时器实际上没有任何作用。 
但如果你没有回收定时器,整个定时器依然有效, 不但定时器无法被内存回收, 
定时器函数中的依赖也无法回收。在这个案例中的 serverData 也无法被回收。 
闭包 
在 JS 开发中,我们会经常用到闭包,一个内部函数,有权访问包含其的外部函数中的变量。 
下面这种情况下,闭包也会造成内存泄露: 
- var theThing = null; 
 - var replaceThing = function () { 
 -  var originalThing = theThing; 
 -  var unused = function () { 
 -  if (originalThing) // 对于 'originalThing'的引用 
 -  console.log("hi"); 
 -  }; 
 -  theThing = { 
 -  longStr: new Array(1000000).join('*'), 
 -  someMethod: function () { 
 -  console.log("message"); 
 -  } 
 -  }; 
 - }; 
 - setInterval(replaceThing, 1000); 
 
  
这段代码,每次调用 replaceThing 时,theThing 获得了包含一个巨大的数组和一个对于新闭包 someMethod 的对象。 
同时 unused 是一个引用了 originalThing 的闭包。 
这个范例的关键在于,闭包之间是共享作用域的,尽管 unused 可能一直没有被调用,但是 someMethod  可能会被调用,就会导致无法对其内存进行回收。 
当这段代码被反复执行时,内存会持续增长。 
DOM 引用 
很多时候, 我们对 Dom 的操作, 会把 Dom 的引用保存在一个数组或者 Map 中。 
- var elements = { 
 -  image: document.getElementById('image') 
 - }; 
 - function doStuff() { 
 -  elements.image.src = 'http://example.com/image_name.png'; 
 - } 
 - function removeImage() { 
 -  document.body.removeChild(document.getElementById('image')); 
 -  // 这个时候我们对于 #image 仍然有一个引用, Image 元素, 仍然无法被内存回收. 
 - } 
 
  
上述案例中,即使我们对于 image 元素进行了移除,但是仍然有对 image 元素的引用,依然无法对齐进行内存回收。 
另外需要注意的一个点是,对于一个 Dom 树的叶子节点的引用。 
举个例子: 如果我们引用了一个表格中的td元素,一旦在 Dom 中删除了整个表格,我们直观的觉得内存回收应该回收除了被引用的 td 外的其他元素。 
但是事实上,这个 td 元素是整个表格的一个子元素,并保留对于其父元素的引用。 
这就会导致对于整个表格,都无法进行内存回收。所以我们要小心处理对于 Dom 元素的引用。 
如何避免内存泄漏 
记住一个原则:不用的东西,及时归还。 
    - 减少不必要的全局变量,使用严格模式避免意外创建全局变量。
 
    - 在你使用完数据后,及时解除引用(闭包中的变量,dom引用,定时器清除)。
 
    - 组织好你的逻辑,避免死循环等造成浏览器卡顿,崩溃的问题。
 
                          (编辑:泰州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |