深入理解 JS 垃圾回收攻略
什么是垃圾回收?
垃圾回收是指删除不再使用的对象(以下简称“垃圾”),以释放内存空间。在 JavaScript 中,相当于销毁没被引用的对象。
如何判断对象是否需要回收?
JavaScript 引擎通过“标记清除”算法进行垃圾回收,它的基本思路是从根对象开始,找到所有已经被引用的对象,标记它们。然后清除所有未被标记的对象。
举个例子:
var a = { b: {} };
var c = a.b;
a = null;
c = null;
对于上述代码,当 a 被赋值为 null 时,a 所指向的对象(包括其中的 b 属性)都已经失去了引用,所以这些对象都会被回收。
如何优化垃圾回收?
避免全局变量
全局变量会一直存在,直到页面关闭,因此建议尽可能使用局部变量。
手动释放不必要的引用
如果一个大对象只使用了一部分,但仍然保留对该对象的引用,则其余部分也会一直保存在内存中。手动将不需要的引用释放掉,可以加快垃圾回收的速度。
举个例子:
function process(data) {
// 使用 data 中的一小部分数据
}
var someData = loadData();
process(someData);
someData = null; // 手动释放引用
避免循环引用
循环引用指两个或多个对象相互引用,导致它们的引用计数永远不为零,无法被垃圾回收器回收。可以通过断开循环引用来解决这个问题,比如将其中一个对象的引用设为 null。
举个例子:
function func() {
var objA = {};
var objB = {};
objA.ref = objB;
objB.ref = objA;
// 使用 objA 和 objB
}
func();
上述代码中,objA 和 objB 彼此相互引用,导致它们都无法被垃圾回收器释放。可以将其中任意一个对象的引用设为 null,打破循环引用即可。
如何监控垃圾回收?
由于垃圾回收是 JavaScript 引擎自动处理的,我们无法直接监控它。但是,可以通过调用 performance.memory 的相关方法获取内存信息,间接地监控垃圾回收情况。
var usedJSHeapSize = performance.memory.usedJSHeapSize;
var totalJSHeapSize = performance.memory.totalJSHeapSize;
var jsHeapSizeLimit = performance.memory.jsHeapSizeLimit;
上述代码中,usedJSHeapSize 表示当前使用中的内存大小,totalJSHeapSize 表示可用的内存总大小,jsHeapSizeLimit 表示分配给 JavaScript 的最大内存。
示例
下面给出一个示例,演示如何通过手动释放不必要的引用来优化垃圾回收:
function func() {
var arr = [];
for (var i = 0; i < 1000000; i++) {
arr.push({ key: 'value' + i });
}
return arr.slice(0, 10); // 只使用数组中的前10个对象
}
var result = func();
// 手动释放除了result数组以外的arr数组中的元素
var arr = result.concat();
result = null;
for (var i = 0; i < arr.length; i++) {
arr[i] = null;
}
arr = null;
在上图的第一个断点处,对于 GC,它必须扫描整个 400 MB 的内存,才能知道 a 都已经失去了引用,可以被释放。在第二个断点处,由于手动释放了不必要的引用,GC 只需扫描 10 MB 的内存即可完成垃圾回收,大大提高了回收效率。
这只是优化垃圾回收的其中一个示例,总体来说,优化垃圾回收需要结合实际情况进行思考、设计。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解 JS 垃圾回收 - Python技术站