React 前端导航

JS 垃圾回收与性能

JS 是使用垃圾回收的语言,也就是说执行环境负责在代码执行时管理内存。基本思路很简单:确定哪些变量不会再使用,然后释放它占用的内存,这个过程是周期性的,即垃圾回收程序每隔一定时间执行一次。在浏览器的发展史上,有两种变量标记策略:标记清理(常用)和引用计数(不常用)。

垃圾回收程序会周期运行,如果内存中分配了很多变量,则可能造成性能损失,尤其在内存有限的移动端设备上,垃圾回收可能明显地拖慢渲染速度和帧速率。开发者不知道什么时候会运行垃圾回收程序,因此最好的办法是在写代码时做到,无论什么时候收集垃圾,都能让它尽快结束工作。

现代垃圾回收程序会基于JS运行环境的探测来决定何时运行,探测机制因引擎而异,但基本上都是根据已分配对象的大小和数量来判断的。

1.通过 const 和 let 声明提升性能

let 和 const 都以块为作用域,所以相比于使用 var,使用这两个新关键字可能会更早的让垃圾回收程序介入,尽早回收应该回收的内存。

2. 隐藏类和删除操作

以 V8 引擎为例,它将 js 代码编译成机器码时会利用'隐藏类'。如果你的代码非常注重性能,那么这一点对你可能非常有用。

运行期间,V8 会将创建的对象与隐藏类关联起来,以跟踪它们的属性特征。能够共享相同隐藏类的对象会更好。比如下面的这段代码:

function Eg(){
  this.title = '标题'
}

const a1 = new Eg()
const a2 = new Eg()

V8会在后台配置,让 a1 和 a2 共享相同的隐藏类,因为它们共享相同的构造函数和原型。假设又添加下面这行代码

a2.author = 'heyu'

这时 a1 和 a2 会对应两个不同的隐藏类。这里的解决方案是避免“先创建再补充”式的动态属性赋值,在构造函数中一次性声明所有属性。如下所示:

function Eg(name){
  this.title = '标题'
  this.author = name
}

const a1 = new Eg('heyu')
const a2 = new Eg()

这样,两个实例基本上一样了,因此可以共享一个隐藏类。如果接下来使用 delete 关键字删除某个属性,那么将使实例不再共享同一个隐藏类

delete a1.title

动态删除属性和动态添加属性导致的结果一样,最佳实践是将不想要的属性设置为null,这样可以保存隐藏类不变,同时也能达到删除引用值供垃圾回收程序回收的效果。

3. 静态分配

为了提升 js 性能,最后要考虑的一点是榨干浏览器了。这里,一个关键的问题是如何减少浏览器执行垃圾回收的次数。开发者无法直接控制什么时候开始收集垃圾,但可以间接控制触发垃圾回收的条件。理论上,如果能够合理使用分配的内存,同时避免多余的垃圾回收,就可以保住因释放内存而损失的性能。

对象更替的速度是浏览器决定何时垃圾回收的一个标准,如果有很多对象被创建,又一下子超出了作用域,那么浏览器会采取更激进的方式调度垃圾回收程序运行,这会降低性能。看下面这个例子

function addVector(a,b){
  const result = new Vector()
  result.x = a.x + b.x
  result.y = a.y + b.y
  return result
}

上述函数会创建一个新对象,然后修改它,最后将其返回。如果这个矢量对象的生命周期很多,那么它会很快失去引用,成为可以被回收的值。假如该函数被频繁调用,那么垃圾回收程序将发现这里对象更替的速度很快,从而频繁地安排垃圾回收。改造方式如下

function addVector(a,b,result){
  result.x = a.x + b.x
  result.y = a.y + b.y
  return result
}

函数的行为没有变,只是需要在其他地方创建矢量参数。一个策略是使用对象池,在初始化的某个时刻创建一个对象池,用来管理一组可回收的对象,当需要使用对象的时候,程序可以向对象池请求一个对象,设置属性,使用它,等操作完成后再把它还给对象池。由于没有发生对象初始化,垃圾回收程序不会发现对象更替,因此它不会那么频繁地运行。

静态分配是优化的一种极端方式,被垃圾回收严重拖后腿这种情况并不多见。

声明:本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。邮箱:farmerlzj@163.com。 本站原创内容未经允许不得转载,或转载时需注明出处: 内容转载自: React前端网:https://qianduan.shop/blogs/detail/240

#js#垃圾回收机制

相关推荐

原型与原型链、继承

原型与原型链、继承简单实现

浏览器中的js事件循环(Event loop)

本文将简述浏览器中的js事件循环机制,帮助我们理解浏览器环境js代码是如何运行的。Javascript的一大特点是单线程,也就意味着同一时间他只能做一件事。事件循环(Event Loop)是为了协调事件,用户交互,UI渲染,网络处理等行为,防止线程阻塞而诞生的。