垃圾回收
正常情况下,一个函数执行完,其中的变量都会被 JS 垃圾回收。比如
function fn() {
const a = "aaa";
console.log(a);
const obj = {
x: 100,
};
console.log(obj);
}
fn();
但是在某些情况下,变量是销毁不了的,因为可能会被再次使用。比如
function fn() {
const obj = {
x: 100,
};
window.obj = obj; // 引用到了全局变量,obj 销毁不了
}
fn();
function genDataFns() {
const data = {}; // 闭包,data 销毁不了
return {
get(key) {
return data[key];
},
set(key, val) {
data[key] = val;
},
};
}
const { get, set } = genDataFns();
垃圾回收算法 - 引用计数
早期的垃圾回收算法,以数据是否被引用来判断要不要回收
// 对象被 a 引用
let a = {
b: {
x: 10,
},
};
let a1 = a; // 又被 a1 引用
let a = 0; // 不再被 a 引用,但仍然被 a1 引用
let a1 = null; // 不再被 a1 引用
// 对象最终没有任何引用,会被回收
但是这个算法有一个缺陷,比如循环引用的变量无法回收
function fn() {
const obj1 = {};
const obj2 = {};
obj1.a = obj2;
obj2.a = obj1; // 循环引用,无法回收 obj1 和 obj2
}
fn();
垃圾回收算法 - 标记清除
现代浏览器使用标记清除算法。根据是否可获得来判断是否回收。
定期从根(即全局变量)开始向下查找,能找到的即保留,找不到的回收。循环引用不再是问题。