这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
前言
吃饱饭才有力气写代码~
昨天讲了JavaScript 的两种标记策略,标记清理和引用计数;今天继续讲相关的性能和内存管理。
性能
我们知道垃圾回收机制是周期性运行的,它的时间调度会影响到系统的性能。尤其是在那些内存有限的移动设备上,垃圾回收可能会很明显地拖慢渲染的速度。
现代垃圾回收程序会根据JavaScript运行时环境的探测来决定什么时候运行。大部分的探测机制都是根据已分配对象的大小和数量来判断的。
ie 浏览器曾经就因为它调度垃圾回收程序方面的问题饱受诟病,它根据分配数决定是否调用垃圾回收程序,比如分配256个变量,满足了,垃圾回收程序就会运行。问题是这个需要那么多变量的脚本可能在整个生命周期都需要那么多变量,结果就导致垃圾回收程序过于频繁地进行。
后来它的策略就调优为动态改变分配变量等会触发垃圾回收的阈值,这样极大地提升了依赖JavaScript的网页在浏览器中的性能。
内存管理
JavaScript 运行在一个内存管理和垃圾回收都很特殊的环境。分配给浏览器的内存通常比分配给桌面软件的要少,这是为了避免运行大量JavaScript的网页耗尽系统内存而导致操作系统崩溃。这个内存限制会影响到变量分配,也影响调用栈以及能够同时在一个线程中执行的语句数量。把内存占用量保存在一个较小的值可以让页面性能更好。优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。
通过 const 和 let 生命提升性能
ES6 增加了上述两个关键字,不仅有利于改善代码风格,也有利于改进垃圾回收的过程。const 和 let都以块为作用域,相比较于var,这俩关键字可能会更早地让垃圾回收程序介入,尽早回收应该回收的内存。
隐藏类和删除操作
避免使用隐藏类的方法就是在构造函数中一次性生命所有属性;
避免删除操作,最佳方法就是把不想要的属性设置为null;
function Article(){
this.tittle = 'Spring';
}
lat a1 = new Article();
let a2 = new Article();
a2.author = 'Tom';
//此时两个实例就会对应两个不同的隐藏类,根据这种操作的频率和隐藏类的大小,就会对性能产生影响。
function Article(str){
this.tittle = 'Spring';
this.author = str;
}
lat a1 = new Article();
let a2 = new Article('Tom');
//此时两个实例基本上就一样了,可以共享一个隐藏类,从而带来潜在的性能提升。
function Article(){
this.tittle = 'Spring';
this.author = 'Tom';
}
lat a1 = new Article();
let a2 = new Article();
delete a1.author;
//此时两个实例虽然用了同一个构造函数,但是不再共享一个隐藏类。
function Article(){
this.tittle = 'Spring';
this.author = 'Tom';
}
lat a1 = new Article();
let a2 = new Article();
a1.author = null;
//这样可以保持隐藏类不变和继续共享,同时也能达到删除引用值供垃圾回收程序回收的效果。