JavaScript 的垃圾收集机制
javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中的使用的内存。而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况,这是造成许多问题的一个根源。在编写javascript程序时候,开发人员不用再关心内存使用的问题,所需内存的分配 以及无用的回收完全实现了自动管理。
JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入相应的环境,就可能用到它们。而当变量离开环境时,这将其 标记为“离开环境”。
常见内存泄漏的原因
虽然JavaScript 会自动垃圾收集,但是如果我们的代码写法不当,会让变量一直处于“进入环境”的状态,无法被回收。下面列一下内存泄露常见的几种情况。
全局变量引起的内存泄漏
function leaks(){
leak = 'xxxxxx';//leak 成为一个全局变量,不会被回收
}
123
闭包引起的内存泄漏
var leaks = (function(){
var leak = 'xxxxxx';// 被闭包所引用,不会被回收
return function(){
console.log(leak);
}
})()
123456
dom清空或删除时,事件未清除导致的内存泄漏
<div id="container">
</div>
$('#container').bind('click', function(){
console.log('click');
}).remove();
// zepto 和原生 js下,#container dom 元素,还在内存里jquery 的 empty和 remove会帮助开发者避免这个问题
12345678
<div id="container">
</div>
$('#container').bind('click', function(){
console.log('click');
}).off('click').remove();
//把事件清除了,即可从内存中移除
1234567
关于这个问题,更详细的内容可以参考我的另外一篇文章关于 dom清空的内存泄漏问题
子元素存在引用引起的内存泄漏
- 黄色是指直接被 js变量所引用,在内存里
- 红色是指间接被 js变量所引用,如上图,refB 被 refA 间接引用,导致即使 refB 变量被清空,也是不会被回收的
- 子元素 refB 由于 parentNode 的间接引用,只要它不被删除,它所有的父元素(图中红色部分)都不会被删除