内存泄漏:
应用程序不再需要占用内存的时候,由于某些原因,内存没有被操作系统或可用内存池回收。
常见的四种引起内存泄露的情况:
1.意外的全局变量:
如果在函数内使用一个未曾声明的变量,则这个变量为直接定义在window下的全局变量;
(同样的使用this.bar,也为window.bar)
//一个未声明的变量的引用在全局对象中创建了一个新变量
//在浏览器的环境中,全局对象是window。
function foo(arg){
bar = "this is a hidden global variable";
}
function foo(arg){
this.bar = "this is a hidden global variable";
}
// 实际上
function foo(arg){
window.bar = "this is a hidden global variable";
}
为了防止这种错误的发生,可以在你的 JavaScript 文件开头添加 ‘use strict’; 语句
2.闭包引起的内存泄漏:
闭包可以导致原有作用域链不释放。
function a() {
function b() {
document.write(aaa);
}
var aaa = 123;
return b;
}
var demo = a();
demo(); //结果打印123
在函数的执行过程中,a开始运行,创建了属于自己的AO,GO,在b创建的时候直接继承a的AO,GO,然后返回b,那么a 的AO,GO,都断开,然而因为b继承了a 的AO,GO所以导致a 的AO里的aaa没有被释放掉,在b 执行的时候会创建属于自己的AO。
3.被遗忘的计时器或回调
setInterval(function() {
var renderer = document.getElementById('renderer');
if(renderer) {
renderer.innerHTML = 456;
}
console.log(1000);
}, 5000); //每5秒执行一次
renderer对象在将来有可能被移除,让interval处理器内部的整个块都变得没有用。但由于interval仍然起作用,处理程序并不能被回收(除非interval停止)。如果interval不能被回收,它的依赖也不可能被回收。这就意味着serverData,大概保存了大量的数据,也不可能被回收。
4.DOM树之外的引用
var elements = {
button:document.getElementById('button'),
image:document.getElementById('image'),
};
function removeButton() {
// button是 body 的后代元素
document.body.removeChild(document.getElementById('button'));
// 此时,仍旧存在一个全局的 #button 的引用
// elements 字典。button 元素仍旧在内存中,不能被回收。
}
removeButton();
此时,同样的 DOM 元素存在两个引用:一个在 DOM 树中,另一个在字典中。将来你决定删除这些行时,需要把两个引用都清除。