关于javascript:一文看懂前端垃圾回收

8次阅读

共计 1542 个字符,预计需要花费 4 分钟才能阅读完成。

简介

javascript 外面变量不再应用,就是垃圾,咱们就应该把它革除掉,免得占用内存。
然而垃圾回收过程是一个近似且不完满的计划,因为某块内存是否还有用,属于“不可判定的”问题,意味着靠算法是解决不了的。
目前支流浏览器应用的是标记革除,在介绍标记革除前先介绍下为什么援用计数会被淘汰。

援用计数

援用计数最早由 Netscape Navigator 3.0 采纳,但很快就遇到了重大的问题:循环援用。
所谓循环援用,就是对象 A 有一个指针指向对象 B,而对象 B 也援用了对象 A。

function problem() {let objectA = new Object(); 
let objectB = new Object();
objectA.someOtherObject = objectB; 
objectB.anotherObject = objectA;
}

在这个例子中,objectA 和 objectB 通过各自的属性互相援用,意味着它们的援用数都是 2。在 标记清理策略下,这不是问题,因为在函数完结后,这两个对象都不在作用域中。而在援用计数策略下 objectA 和 objectB 在函数完结后还会存在,因为它们的援用数永远不会变成 0。如果函数被屡次调 用,则会导致大量内存永远不会被开释。为此,Netscape 在 4.0 版放弃了援用计数,转而采纳标记清理。

标记革除

  • 1. 垃圾回收程序运行的时候,会标记内存中存储的所有变量。
  • 2. 而后它会将所有在上下文中的变量,以及被在上下文中的变量援用的变量的标记去掉。
  • 3. 在此之后再被加上标记的变量就是待删除的了,起因是任何在上下文中的变量都拜访不到它们了。

可达性

这里介绍下第二步骤的一个实现。
可达性就行可拜访性,window(globle)能拜访某个变量 A(不论通过几层取值),那 A 就是可达的,那么 A 就有可能再将来会被用,A 就不会被删除。
咱们看一下下图就能明确,右边可达,左边不可达,左边会再某个阶段会 v8 引擎回收

相干概念

闭包

明确了垃圾回收的概念,了解闭包就简略多了。
闭包为啥不销毁,因为以后函数执行完的返回值(个别是个函数)被外层上下文中的某个变量援用了,所以闭包中的环境可达,所以不会被销毁。
然而也因为不会被销毁,所以咱们应该留神一下内存透露,也就是如果闭包占用的内存特地多,又把它赋给全局变量。而且这个操作咱们是一直的进行的,那个内存就会越占越多,也就是产生了内存透露。

weakmap

还有个相干的考点,就是 weakmap 为什么不会被 gc(Garbage Collection,垃圾收集)
因为它对于值的援用都是不计入垃圾回收机制的,所以名字外面才会有一个 ”Weak”,示意这是弱援用。
避免内存透露咱们须要手动置 null。
map 的键是对象,这个援用当于永远可达,这样不好,会有内存透露。
为了防止咱们遗记置 Null,es6 增加了 weakmap 这种数据结构,只有所援用的对象的其余援用都被革除,垃圾回收机制就会开释该对象所占用的内存。也就是说,一旦不再须要,WeakMap 外面的键名对象和所对应的键值对会主动隐没,不必手动删除援用

性能优化

  • 通过 const 和 let 申明晋升性能
    因为 const 和 let 都以块(而非函数)为作用域,所以相比于应用 var,应用这两个新关键字可能会更早地让垃圾回收程序染指,尽早回收应该回收的内存。
  • 多解除援用(闭包)
    优化内存占用的最佳伎俩就是保障在执行代码时只保留必要的数据。如果数据不再必要,那么把它设置为 null,从而开释其援用。这也能够叫 作解除援用。这个倡议最适宜全局变量和全局对象的属性。局部变量在超出作用域后会被主动解除援用,

    参考资料

    1. 垃圾回收
    2.JavaScript 内存透露教程
    3. 前端面试:谈谈 JS 垃圾回收机制
    4.MDN- 内存治理
    5.javascript 高级程序设计第 4 版本

正文完
 0