JavsScript在变量创建的时候分配内存,然后在它们不再使用时“自动”释放,就是被称为垃圾回收。“自动”这个词很容易让人混淆,让我们误以为不需要去管理内存。其实这个“自动”也有其处理的逻辑,深入地了解其运行机制,能让我们写出更健壮的JavaScript代码,免去内存泄漏的烦恼。
内存生命周期
不管什么程序语言,内存生命周期基本是一致的:
- 分配你所需要的内存
- 使用分配到的内存(读/写)
- 不需要时将其回收
其中,第一步和第二步并不需要我们关心。我们关注的是:什么情况才会被当成不需要的时候。
垃圾回收
JavaScript具有自动垃圾回收机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。它的原理其实很简单:找到那些不再继续使用的变量,然后释放其占用的内存。
我们都知道局部函数的变量都是在运行的时候分配内存,然后执行结束的时候释放内存。在这种情况下,很容易判断变量是否还有存在的必要。但并非所有情况都这么容易判断的。因此垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来回收其占用的内存。用于标识无用变量的策略通常有两种:
- Reference-counting(引用计数)
- Mark-and-sweep(标记清除)
引用
一个对象如果有访问另一个对象的权限,就叫做一个对象引用另一个对象。
引用计数
其实这是一个很粗略的方式:只要一个对象没有被引用,那就把它当垃圾处理了。这个算法很简单实现,但是有一个致命的问题就是无法解决循环引用的问题:
var div;
window.onload = function(){
div = document.getElementById("myDivElement");
div.circularReference = div;
div.lotsOfData = new Array(10000).join("*");
};
这时DOM 元素myDivElement
就永远不会被回收了。
标记清除
这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。
这个算法假定是有一系列的被称为root的对象,也就是根对象,在JavaScript就是全局对象window
。
然后垃圾回收器就定期地从全局对象开始扫描,寻找所有被全局对象或其他对象引用的对象。
这句话略绕口,简而言之就是,首先寻找到所有被全局对象引用的对象,然后再寻找这些对象所引用的对象,以此循环递归寻找到所有的可被访问对象。
这样,垃圾回收器就可以知道所有的可访问对象和不可访问对象。
本文主要内容参考:Memory Management
说了两种回收算法,但是你标题中的管理及重点提到的实现回收并没有说明啊。js的自动回收机制的实现算法就是那两种算法,不过以web浏览器的实现来说,不同的浏览器实现不一样,IE10之前(印象中是,记不清了)用的是引用计数法,webkit内核的浏览器使用的是标记清除法,火狐比较特别两者结合的。但是具体到小程序在Android和iOS中运行环境并不一样,不好说啊。
最关键的还是你文章中的如何回收的具体实现在小程序中的具体做法并没有指明啊!
跟小程序有什么关系吗?