JS会在创建变量时自动分配内存,在不使用的时候会自动周期性的释放内存,释放的过程就叫 "垃圾回收"。这个机制有好的一面,当然也也有不好的一面。一方面自动分配内存减轻了开发者的负担,开发者不用过多的去关注内存使用,但是另一方面,正是因为因为是自动回收,所以如果不清楚回收的机制,会很容易造成混乱,而混乱就很容易造成"内存泄漏".由于是自动回收,所以就存在一个 "内存是否需要被回收的" 的问题,但是这个问题的判定在程序中意味着无法通过某个算法去准确完整的解决,后面探讨的回收机制只能有限的去解决一般的问题。

回收算法

垃圾回收对是否需要回收的问题主要依赖于对变量的判定是否可访问,由此衍生出两种主要的回收算法:

标记清理

标记清理是js最常用的回收策略,2012年后所有浏览器都使用了这种策略,此后的对回收策略的改进也是基于这个策略的改进。其策略是:

  1. 变量进入上下文,也可理解为作用域,会加上标记,证明其存在于该上下文;
  2. 将所有在上下文中的变量以及上下文中被访问引用的变量标记去掉,表明这些变量活跃有用;
  3. 在此之后再被加上标记的变量标记为准备删除的变量,因为上下文中的变量已经无法访问它们;
  4. 执行内存清理,销毁带标记的所有非活跃值并回收之前被占用的内存;

https://github.com/zhansingsong/js-leakage-patterns/blob/master/JavaScript内存那点事/images/mark-sweep.gif?raw=true

局限

引用计数

引用计数策略相对而言不常用,因为弊端较多。其思路是对每个值记录它被引用的次数,通过最后对次数的判断(引用数为0)来决定是否保留,具体的规则有