常見的內存泄露案例
1,意外創建的全局變量
解決辦法:
可以通過加上 ‘use strict’ 啓用嚴格模式來避免這類問題, 嚴格模式會阻止你創建意外的全局變量.
function foo() {
bar1 = 'some text 1'; // 沒有聲明變量 實際上是全局變量 => window.bar1
this.bar2 = 'some text 2' // 全局變量 => window.bar2
var bar3 = 'bar3在函數執行時存入內存,執行完畢則被js的垃圾回收機制自動從內存中銷燬,不再佔用內存,因此無法在外部調用到。而bar1,bar2由於是全局變量,掛載在window下,所以無法從內存中銷燬,因此bar1、bar2在控制檯可以打印出其值,而bar3則不行';
console.log(bar3);
}
foo();
2,被遺忘的定時器和回調函數
如果你沒有清空定時器,整個定時器依然有效, 不但定時器無法被內存回收, 定時器函數中的依賴也無法回收
var serverData = function(){
var age = (Math.random()*10 | 0) + 20;
return {
age:age,
name:'July'
}
};
setInterval(function() {
var renderer = document.getElementById('renderer');
if(renderer) {
renderer.innerHTML = JSON.stringify(serverData());
}
}, 2000);
3,未清除 dom 元素的引用
dom元素已經被移除,但 對 dom元素的引用沒有解除,會導致內存泄漏。
解決辦法:手工移除,將引用指向null
function removeButton() {
var btn = document.getElementById('button'); //引用dom元素
document.body.removeChild(btn); // 雖然我們用removeChild移除了button, 但是在btn對象裏保存着#button的引用,換言之, DOM元素還在內存裏面.
btn = null; //清空引用
}
4,循環引用
垃圾回收算法主要依賴於引用的概念。主要有兩種算法:計數算法(IE瀏覽器)、 標記清除算法
循環引用在計數算法的回收機制下會導致內存泄漏,而標記清除算法則不會。
function fn() {
var a = {};
var b = {};
a.pro = b;
b.pro = a;
}
fn();
- a和b的引用次數都是2,fn()執行完畢後,兩個對象都已經離開環境。
- 在標記清除方式下是沒有問題的,但是在引用計數策略下,a和b的引用次數不爲0,不會被垃圾回收器回收內存。如果fn函數被大量調用,就會造成內存泄漏。
- IE中的垃圾收集機制採用的是引用計數算法
5,閉包 (會引起內存泄露嗎)
常見的閉包產生內存泄漏問題的根本原因就是沒有及時的斷開對變量的引用