前端性能提升系列(根据学习工作中遇到的问题不定期更新)

一、垃圾回收

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

二、内存管理

将内存占用量保持在一个较小的值可以让页面性能更好。优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为 null,从而释放其引用。这也可以叫作解除引用。这个建议最适合全局变量和全局对象的属性。局部变量在超出作用域后会被自动解除引用,如下面的例子所示:

function xingneng1(name){
	let a = new Object();
	a.name= name;
	return a ;
}
let b = xingneng1("Rose")
// 接触 b 对值的引用 
b = null;
在上面的代码中,b 保存着 xingneng1()函数调用返回的值。在xingneng1内部,a 创建了一个对象并给他添加了一个name 属性,然后 a 作为函数被返回,并被赋值给 b 。a在xingneng1()执行完成超出上下文后会自动被接触引用,不需要显示处理。但b是一个全局变量,最后一行,在不需要时b时手动解除引用。
注意:解除对一个值的引用不会自动导致相关内存被回收。接触引用的关键在于确保相关的值已经不在上下文里了,因此他在下次垃圾回收时会被回收。

三、隐藏类和删除操作

比如下面的代码:

function Article() {
	this.title = 'INIcbud ciuwbi';   // 随便敲的
}
let a1 = new Article();
let a2 = new Article();
a2.author = 'Rose';

此时,两个 Article 实例就会对应两个不同的隐藏类,根据这种操作的频率和隐藏类的大小,这有可能对性能产生明显影响。
解决方案就是避免 JavaScript 的“先创建再补充(ready-fire-aim)”式的动态属性赋值,并在构造函数中一次性声明所有属性

function Article(opt_name) {
	this.title = 'HQIOCNA CBIQCN';
	this.name = opt_name; 
}
let a1 = new Article();
let a2 = new Article("Rose");

由于 delete 关键字会导致生成相同的隐藏类片段,最佳实践是把不想要的属性设置为 null,这样可以保持隐藏类不变和继续共享,同时也能达到删除引用值供垃圾回收程序回收的效果。

function Article(opt_name) {
	this.title = 'HQIOCNA CBIQCN';
	this.name = opt_name; 
}
let a1 = new Article();
let a2 = new Article("Rose");
a1.name = null;

四、选择 Object 还是 Map

  1. 内存占用方面
    给定固定大小的内存,Map 大约可以比 Object 多存储 50%的键/值对
  2. 插入性能
    Map 会稍微快一些
  3. 查找速度
    代码设计大量查找操作,某些情况下选择 Object 更好一些
  4. 删除性能
    如果代码涉及大量删除操作,那么应该选择 Map

五、弱映射(WeakMap)——DOM节点元数据

当节点从 DOM 树中被删除后,垃圾回收程序就可以立即释放内存。

const a = new WeakMap();
const loginButton = document.querySelector('#login');
// 给这个节点关联一些元数据
a.set(loginButton, {disabled: true});

六、创建新对象

  1. 使用 Object.setPrototypeOf()重写一个对象的原型继承关系
  • 这会涉及所有访问了那些修改过 [[Prototype]]的对象的代码。
  • 会造成性能下降
let a = { b: 2 }; 
let person = { 
 name: 'Rose' 
}; 
Object.setPrototypeOf(person, a); 
console.log(person.name); // Matt 
console.log(person.b); // 2 
console.log(Object.getPrototypeOf(person) === a); // true 
  1. 为避免使用 Object.setPrototypeOf()可能造成的性能下降。可以通过 Object.create() 来创建一个新对象,同时为其指定原型
let a = { b: 2 }; 
let person = Object.create(a);
person.name = 'Rose'; 

console.log(person.name); // Matt 
console.log(person.b); // 2 
console.log(Object.getPrototypeOf(person) === a);
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kcuwu.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值