specialgirlgotoheaven / MyBlog

MyBlog
0 stars 0 forks source link

造成内存泄漏的情况 #140

Open specialgirlgotoheaven opened 5 years ago

specialgirlgotoheaven commented 5 years ago

1.全局变量 2.setInterval 3.闭包 4.DOM引用 5.echart 6.事件监听(EventListener)

  1. console.log打印的对象不能被垃圾回收,可能会导致内存泄露。 8.循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

1、给DOM对象添加的属性是一个对象的引用。范例:  var MyObject = {};  document.getElementById('myDiv').myProp = MyObject;  解决方法:  在window.onunload事件中写上: document.getElementById('myDiv').myProp = null; 

2、DOM对象与JS对象相互引用。范例:  function Encapsulator(element) {  this.elementReference = element;  element.myProp = this;  }  new Encapsulator(document.getElementById('myDiv'));  解决方法:  在onunload事件中写上: document.getElementById('myDiv').myProp = null; 

3、给DOM对象用attachEvent绑定事件。范例:  function doClick() {}  element.attachEvent("onclick", doClick);  解决方法:  在onunload事件中写上: element.detachEvent('onclick', doClick); 

4、从外到内执行appendChild。这时即使调用removeChild也无法释放。范例:  var parentDiv = document.createElement("div");  var childDiv = document.createElement("div");  document.body.appendChild(parentDiv);  parentDiv.appendChild(childDiv);  解决方法:  从内到外执行appendChild:  var parentDiv = document.createElement("div");  var childDiv = document.createElement("div");  parentDiv.appendChild(childDiv);  document.body.appendChild(parentDiv); 

5、反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)。范例:  for(i = 0; i < 5000; i++) {  hostElement.text = "asdfasdfasdf";  }  这种方式相当于定义了5000个属性!  解决方法:  其实没什么解决方法:就是编程的时候尽量避免出现这种情况咯~~ 

但如果通过这么几个模式去check项目里的代码简直如大海捞针,我只有凭经验预测最有可能泄漏的几个点,再通过排除法,去掉先相关代码,再看内存是否泄漏。我预计会有以下几种情况造成泄漏:

频繁操作iframe 动态创建DOM 事件绑定 Ext框架本身 经过排查发现项目这么几个点内存泄漏较为严重:

对iframe里面的页面大量绑定键盘事件 在iframe里面的页面动态创建DOM iframe的刷新 Ext本身 对于这些问题我的解决方案如下:

离开iframe里的页面之前删除所有的事件绑定,删除所有动态创建的DOM 刷新iframe内容之前调用 iframe.contentWindow.document.write(''); iframe.contentWindow.document.close(); 强制释放iframe里的页面元素 修改Ext某些点。 比如Ext.getDOC() getDoc : function(){ //原实现 //return Ext.get(document); //修改后 var f = function() { }; f.prototype = Ext.Element.prototype; var docEl = new f(); docEl.dom = document; return docEl; } 具体是什么原因还没查清,不过修改后确实内存释放了不少。 修改Ext垃圾回收相关代码。及时删除垃圾回收的轮询。

specialgirlgotoheaven commented 5 years ago

前端如何检查内存泄露?

(1).使用Chrome的开发者工具profiles来进行快照对比。

(2).如果是在Node环境下,可以用Node提供的process.memoryUsage()方法来检查内存泄露:

rss (resident set size) : 所有内存占用,包括指令区和堆栈。

heapTotal : "堆"占用的内存,包括用到的和未用到的。

heapUsed : 用到的堆。

external : V8引擎内部C++对象占用的内存。

判断内存泄露以heapUsed为准。

specialgirlgotoheaven commented 5 years ago

如何处理内存泄漏?

变量导致的内存泄露,将变量清除 a = null 即可。

事件监听导致的内存泄露,监听后移除即可

specialgirlgotoheaven commented 5 years ago

ES6 考虑到了这一点,推出了两种新的数据结构:WeakSet 和 WeakMap。它们对于值的引用都是不计入垃圾回收机制的,所以名字里面才会有一个"Weak",表示这是弱引用。

下面以 WeakMap 为例,看看它是怎么解决内存泄漏的。

const wm = new WeakMap(); const element = document.getElementById('example'); wm.set(element, 'some information'); wm.get(element) // "some information"

上面代码中,先新建一个 Weakmap 实例。然后,将一个 DOM 节点作为键名存入该实例,并将一些附加信息作为键值,一起存放在 WeakMap 里面。这时,WeakMap 里面对element的引用就是弱引用,不会被计入垃圾回收机制。

也就是说,DOM 节点对象的引用计数是1,而不是2。这时,一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放。Weakmap 保存的这个键值对,也会自动消失。

基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。

specialgirlgotoheaven commented 5 years ago

http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

specialgirlgotoheaven commented 5 years ago

https://blog.csdn.net/oliver_web/article/details/53957021

specialgirlgotoheaven commented 5 years ago

浏览器内存泄漏 https://blog.csdn.net/sinoknots/article/details/51350966