http://www.ruanyifeng.com/blog/2017/04/memory-leak.htmlhtml
什麼是內存泄漏?
內存泄漏是指再也不用到的內存,沒有及時釋放。既不能使用,又不能回收。node
程序的運行須要內存。對於持續運行的進程,若是不及時釋放再也不用到的內存,內存佔用愈來愈高,輕則影響系統性能,重則致使進程崩潰。閉包
要了解 JS 內存泄漏的幾種狀況,咱們首先來了解一下 JS 的內存是如何管理的,即 JS 的垃圾收集機制。dom
垃圾收集機制
Javascript 具備自動垃圾收集機制,也就是說,執行環境會負責管理代碼執行過程當中的使用的內存。所需內存的分配 以及無用的回收 徹底實現了自動管理。函數
JavaScript 垃圾回收機制很簡單:找出再也不使用的變量,而後釋放掉其佔用的內存。可是這個過程不是時時的,由於其開銷比較大,因此垃圾回收器會按照固定的時間間隔週期性的執行。性能
JavaScript 中最經常使用的垃圾收集方式有 2 種:標記清除和引用計數。url
1)「標記清除」——當變量進入環境(例如,在函數中聲明一個變量)時,就將這個變量標記爲「進入環境」。當變量離開環境時,這將其 標記爲「離開環境」。.net
從邏輯上講,永遠不能釋放進入環境的變量所佔的內存,由於只要執行流進入相應的環境,就可能用到它們。component
function fun(){
var a = 1;//被標記 進入環境
var b= 2;//被標記 進入環境
}
fun();//執行完畢以後,a,b 被標記離開環境,被回收
若是咱們的代碼寫法不當,會讓變量一直處於「進入環境」的狀態,沒法被回收。htm
2)「引用計數」——語言引擎有一張」引用表」,跟蹤記錄每一個值被引用的次數。
若是一個值的引用次數是0,就表示這個值再也不用到了,所以能夠將這塊內存釋放。
若是一個值再也不須要了,引用數卻不爲0,垃圾回收機制沒法釋放這塊內存,從而致使內存泄漏。
那些很佔空間的值,一旦再也不用到,你必須檢查是否還存在對它們的引用。若是是的話,就必須手動解除引用。
function test(){
var a = {} ; //a的引用次數爲0
var b = a ; //a的引用次數加1,爲1
var c = a; //a的引用次數再加1,爲2
var b ={}; //a的引用次數減1,爲1
}
致使內存泄漏的幾種狀況
1. 意外的全局變量
function leaks(){
leak = 'xxxxxx';//leak 成爲一個全局變量,不會被回收
}
調用完函數之後,變量仍然存在,致使泄漏.
你能夠經過加上 ‘use strict’ 啓用嚴格模式來避免這類問題, 嚴格模式會阻止你建立意外的全局變量.
2. 閉包
閉包能夠維持函數內局部變量,使其得不到釋放。
解決辦法:在函數外部定義事件處理函數,解除閉包。或在閉包中,刪除沒用的屬性以減小對內存的消耗。或在外部函數中刪除對DOM的引用
function bindEvent()
{
var obj=document.createElement("XXX");
obj.onclick=function(){
//Even if it's a empty function
}
obj=null;
}
3. 未清除 dom 元素的引用
dom 元素移除,但 對 dom 元素的引用沒有解除,會致使內存泄漏。
解決辦法:手工移除。
var elements = {
button: document.getElementById('button'),
image: document.getElementById('image')
}
function doStuff() {
image.src = 'http://some.url/image';
button.click();
console.log(text.innerHTML);
}
function removeButton() {
document.body.removeChild(document.getElementById('button'));
// 雖然咱們用removeChild移除了button, 可是還在elements對象裏保存着#button的引用
// 換言之, DOM元素還在內存裏面.
}
4.循環引用
循環引用 在引用計數策略下會致使內存泄漏,標記清除不會。
解決辦法:手工解除循環引用。
function fn() {
var a = {};
var b = {};
a.pro = b;
b.pro = a;
}
fn();
a和b的引用次數都是2,fn()執行完畢後,兩個對象都已經離開環境。
在標記清除方式下是沒有問題的,可是在引用計數策略下,a和b的引用次數不爲0,不會被垃圾回收器回收內存。若是fn函數被大量調用,就會形成內存泄漏。
IE中的BOM和DOM中的對象使用C++以COM(component Object Model,組件對象模型)對象的形式實現而COM對象的垃圾收集機制採用的是引用計數策略。換句話說,只要在IE中涉及COM對象,就會存在循環引用的問題。
var element = document.getElementById("some_element");var myObject = new Object();myObject.e = element;element.o = myObject;//手工斷開它們之間的鏈接myObject.element=null;element.someObject=null;5. 被遺忘的計時器或回調var someResource = getData();setInterval(function() { var node = document.getElementById('Node'); if(node) { node.innerHTML = JSON.stringify(someResource)); }}, 1000);原文:https://blog.csdn.net/meijory/article/details/76839072 版權聲明:本文爲博主原創文章,轉載請附上博文連接!