1、什么是垃圾
- 不再被需要的,就是垃圾
- 全局变量都不是垃圾,有可能还会被使用到,如
var a = { name: 'xxx' } - 全局变量 = null,则原来的对象就变成了垃圾,如
a = null - 局部变量在调用这个函数以后,就变成了垃圾,因为不会再用到这个变量。就算再次调用该函数,使用到的变量也不是原来的变量了
- 如
function fn(){ var b = 1 console.log(b) } fn()
- 如
- 全局变量都不是垃圾,有可能还会被使用到,如
- 如果存在双引用
- 删除其中一个引用,该对象还是存在的
- 如:
var a = { name: 'xxx' }
var b = a
a = null
- 如果是环引用呢?
- 如:
- 如果引用 father 的变量都松开了手,那么 father 这个对象就变成了垃圾
- 如果删除了 father 和 mother 与外界的联系 family,那么 father 和 mother 这两个对象也会变成垃圾
- 如:
2、关于垃圾回收算法
-
标记清除算法(Mark-Swipe):从全局作用域开始,把所有用到的变量都标记一下,如果标记过的变量还有其他引用到的变量,就再次进行标记,一直标记到没有新的引用的对象,标记结束。然后把其他没有标记的对象全部清除掉。
- 图示:
- 标记算法存在的缺点:由于 JS 是单线程的,当对象数量过多时,就会耗费过多的时间来加载 JS。
- 改进方法:分代回收(分为新生代和老一代)、分批遍历、空闲时间回收
- 图示:
-
引用计数算法:本质是跟踪记录每个值被引用的次数。其执行机制如下:
- 当声明一个变量并将一个引用类型值赋值给该变量时,这个值的引用次数为1;
- 若同一个值(变量)又被赋值给另一个变量,则该值的引用次数加1;
- 但是如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1;
- 当这个值的引用次数为0时,则无法再访问这个值,就可回收其占用的内存空间。
-
其他算法还包括:
- 分代回收
- Scavenge 算法
- 标记-紧缩算法
- ...
- 这些算法暂时还并不是很了解,之后随着学习的深入,相信可以慢慢的更好的理解