內存泄漏指因爲疏忽或錯誤形成程序未能釋放已經再也不使用的內存。內存泄漏並不是指內存在物理上的消失,而是應用程序分配某段內存後,因爲設計錯誤,致使在釋放該段內存以前就失去了對該段內存的控制,從而形成了內存的浪費。這裏就講一些常見會帶來內存泄露的緣由。javascript
JavaScript自由的其中一種方式是它能夠處理沒有聲明的變量:一個未聲明的變量的引用在全局對象中建立了一個新變量。在瀏覽器的環境中,全局對象是window。
function foo(){ name = '前端曰'; } // 實際上是把name變量掛載在window對象上 function foo(){ window.name = '前端曰'; } // 又或者 function foo(){ this.name = '前端曰'; } foo() // 其實這裏的this就是指向的window對象
這樣無心中一個意外的全局變量就被建立了,爲了阻止這種錯誤發生,在你的Javascript文件最前面添加 'use strict;'
。這開啓瞭解析JavaScript的阻止意外全局的更嚴格的模式。或者本身注意好變量的定義!前端
在js的內存管理環境中,對象 A 若是有訪問對象 B 的權限,叫作對象 A 引用對象 B。引用計數的策略是將「對象是否再也不須要」簡化成「對象有沒有其餘對象引用到它」,若是沒有對象引用這個對象,那麼這個對象將會被回收 。java
function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2 obj2.a = obj1; // obj2 引用 obj1 }
當函數 func 執行結束後,返回值爲 undefined,因此整個函數以及內部的變量都應該被回收,但根據引用計數方法,obj1 和 obj2 的引用次數都不爲 0,因此他們不會被回收。要解決循環引用的問題,最好是在不使用它們的時候手工將它們設爲空。node
解決方案:obj1
和 obj2
都設爲 null
。瀏覽器
閉包:匿名函數能夠訪問父級做用域的變量。閉包
var names = (function(){ var name = 'js-say'; return function(){ console.log(name); } })()
閉包會形成對象引用的生命週期脫離當前函數的上下文,若是閉包若是使用不當,能夠致使環形引用(circular reference),相似於死鎖,只能避免,沒法發生以後解決,即便有垃圾回收也仍是會內存泄露。函數
在咱們的平常需求中,可能會常常試用到 setInterval/setTimeout
,可是使用完以後一般忘記清理。this
var someResource = getData(); setInterval(function() { var node = document.getElementById('Node'); if(node) { // 處理 node 和 someResource node.innerHTML = JSON.stringify(someResource)); } }, 1000);
setInterval/setTimeout
中的 this
指向的是window對象,因此內部定義的變量也掛載到了全局;if
內引用了 someResource
變量,若是沒有清除 setInterval/setTimeout
的話someResource
也得不到釋放;同理其實 setTimeout
也同樣。因此咱們用完須要記得去 clearInterval/clearTimeout
。spa
var refA = document.getElementById('refA'); document.body.removeChild(refA); // #refA不能回收,由於存在變量refA對它的引用。將其對#refA引用釋放,但仍是沒法回收#refA。
解決方案:refA = null
。設計
var MyObject = {}; document.getElementById('myDiv').myProp = MyObject;
解決方案:在頁面 onunload
事件中釋放 document.getElementById('myDiv').myProp = null;
。
DOM被刪除或清空沒有清楚綁定事件這種狀況應該是比較常見的,同時也應該是比較容易被忽略的。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ document.getElementById("myDiv").innerHTML = "wechat: js-say"; } document.body.removeChild(btn); btn = null;
這裏把DOM移除了,可是綁定的事件仍沒被移除,會引發內存泄露因此須要清除事件。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ btn.onclick = null; document.getElementById("myDiv").innerHTML = "wechat: js-say"; } document.body.removeChild(btn); btn = null;
我本身運營的公衆號,記錄我本身的成長!
每週至少一篇博客,拒絕拖延從我作起!
公衆號:前端曰
公衆號ID:js-say
ps:是(yue)不是(ri)