垃圾回收的两种实现方式
垃圾回收有两种实现方式,分别是标记清除法和引用计数法
引用计数法
低版本的 IE 的垃圾回收机制 每被引用一次该变量统计加1,不再引用减1,直到为0才可以销毁。
let obj1 = {};
let obj2 = {
b: obj1
};
obj1.a = obj2;
此时计数永远不可能为 0,只能手动将变量的内存释放
obj1.a = null;
obj2.b = null;
这是循环引用问题,在此机制下比较容易产生内存泄漏问题。
标记清除法
一般认为当变量进入执行环境时标记为“进入”,当变量离开执行环境时则标记为“离开”。变量对象存在栈中,在出栈之后标记为离开,接着销毁。这个是有点问题的。
比如在常见得闭包中,闭包被引用的变量也应该在执行结束后被销毁才对,但是却被保存在了内存中。
标记清除法并非是标记执行栈的进出,而是从根开始遍历,也是一个找引用关系的过程,环境中的变量引用的变量不会被计入,环境变量也不会被记入。他们会存入堆而不是栈。
内存泄露问题
- 闭包:优点明显,将内部变量变成它的私有属性。但是内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题
- 全局变量和未销毁的定时器 很多人设置定时器后,不会再管他了,这会造成内存泄露,应该在使用结束清除。
let timeSet = setTimeout(_=>{
代码块
clearTimeout(timeSet);
},1000)
- 全局变量
- 很多时候并不是需要全局变量,需要的是一个局部作用域
//自执行函数
(_ => {
let a
})()