JS 内存泄露 — JS Memory leak
♻️

JS 内存泄露 — JS Memory leak

Property
FrontEnd
Year
2022
Author
Tweet
说道内存泄露就得先提起垃圾回收

垃圾回收 GC(Garbage Collection)

JS 会在创建变量时自动分配内存,在不使用的时候就会周期性的自动释放内存,释放的过程就叫做“垃圾回收”
这个机制有好的一面也有不好的一面,好的一面是自动分配内存减轻了开发者的负担,但另一方面如果使用不当可能会造成内存泄漏的问题
所以就需要去了解垃圾回收背后的原理及算法
例:
  1. 普通变量
function fn() { const a = 'a'; console.log(a); const b = { x: 10 }; console.log(b) } fn();
如上面的代码所示,fn() 执行完了之后,变量 a 和变量 b 就没有用了,过段时间后 JS 引擎就会自动回收这两个“垃圾”
  1. 被引用
function fn() { const a = 'a'; window.a = a; } fn();
但是如果是这样的话就不会被回收,因为变量 a 会一直被 window 引用
  1. 闭包
同样,闭包的一大作用就是为了外部可以访问内部的变量,所以也不会被回收

回收算法

标记清理(

标记清理的逻辑如下
  • 垃圾回收器获取根并“标记”(记住)它们。
  • 然后它访问并“标记”所有来自它们的引用。
  • 然后它访问标记的对象并标记它们的引用。所有被访问的对象都被记住,以便以后不再访问同一个对象两次。
  • 以此类推,直到有未访问的引用(可以从根访问)为止。
  • 除标记的对象外,所有对象都被删除。
需要注意的是,循环引用由于不能被标记,所以也会被垃圾回收机制回收

引用计数(

引用计数不常用,是之前低版本浏览器使用的一种方式,思路是记录每个变量被引用的次数,通过最后判断引用的次数是否为0,来决定是否保留
局限
局限于循环引用
function fn() { const a = { x: 100 } const b = { y: 200 } a.c = b; b.d = a; }
这种循环引用引用次数不会为0,如果这个方法被多次调用,可能会引起内存泄露的问题

JS 闭包是内存泄露吗

答案是不是的,内存泄露是非预期的,闭包的作用就是获取内部变量,是在预期内的
总的来说闭包是不可被回收的,不属于内存泄露。

如何检测 JS 内存泄露

可以使用浏览器自带的 Performance
notion image

JS 内存泄露的场景有哪些

  1. 被全局变量、函数引用时,组件销毁时未清除
  1. 被全局事件、定时器引用时,组件销毁时未清除
  1. 被自定义事件引用,组件销毁时未清除