什么是内存泄漏?
程序的运行都是需要内存的。只要内存提出要求,操作系统或运行时(runtime)必须供给内存。
当应用程序中的一些代码变量不再需要用到内存时,但是没有被操作系统或者可用内存池回收,就说明它发生了内存泄漏。
char * buffer;
buffer = (char*) malloc(42);
// Do something with buffer
free(buffer);
有些语言(比如C语言)没有垃圾回收机制,则必须由程序员手动进行回收。所以大多数语言提供自动内存管理,这被称为“垃圾回收机制”。
如上图的C语言片段,程序员用malloc方法申请内存,用free方法手动对内存进行回收。
我们今天要讨论的是JavaScript(以下称JS)是一个有着“垃圾回收机制”的语言,“垃圾回收机制”通过周期性的检查先前的分配的内存是否会被再次使用。
如何避免JS内存泄漏?
1.避免误建全局变量
众所周知,在JS中使用未定义的变量,会在全局对象中定义一个新变量。在浏览器中,全局变量是window
function foo(arg) {
bar = "this is a hidden global variable";
}
其实真相是
function foo(arg)
{
window.bar="this is an explicit global variable";
}
或者更糟的情况
function foo() {
this.variable = "potential accidental global";
}
// Foo 调用自己,this 指向了全局对象(window)
// 而不是 undefined
foo();
其实这些都是因为忘记声明变量或者不严谨造成的,这些可以用“严格模式”来避免(use strict)
//use strict
1.全局变量显式声明
2.禁止this关键字指向全局对象
3.禁止删除变量
4.对象不能有重名的属性
5.函数不能有重名的参数
但是仍然有一些我们事先声明且明确的全局变量产生的垃圾是无法回收的,所以我们要尽量在使用完这个全局变量后,给这个全局变量赋值为null或者重新定义;尽量少用全局变量存储大量数据
2.注意定时器或回调函数的使用
根据个人曾经用cocos2d-javascript做游戏的经验,当我在场景调用多个定时器的话,有时候内存会突然升高,主要是因为定时器的大量使用和循环次数太频繁。
所以使用定时器不可避免,但尽量少使用,尽量在使用完定时器后,使用clearInterval或者clearTimeout。
3.DOM操作引起的内存泄漏
1) 给DOM对象添加的属性是另一个对象的引用。
var testObject = {};
document.getElementById('idname').property = testObject; //如果DOM不被消除,则testObject会一直存在,造成内存泄漏
解决方法:给DOM对象添加的属性赋值“null”
document.getElementById('idname').property =null;
2) 给DOM对象用attachEvent方法绑定事件
function doClick() {}
element.attachEvent("onclick", doClick);
解决方法:给DOM对象删除注册
element.detachEvent('onclick', doClick);
3) 从外到内执行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);
4) 反复重写一个同一个属性会占用大量的内存(关闭浏览器后会被释放)
for(i = 0; i < 5000; i++) {
hostElement.text = "asdfasdfasdf";
}
解决方法:尽量避免这样的情况发生。
4) 闭包和循环引用引起的内存泄漏
<目前没有理解什么意思,待理解后补充>