《高性能JavaScript》第6-8章

2021-11-09  本文已影响0人  前端艾希

一、快速响应的用户界面

浏览器限制JavaScript运行时间的策略:

Robert Miller在1968年的研究中提到单个脚本操作不应该超过100ms,后来一些学者也重申了相近的观点。因为当界面在100ms内无法响应用户的操作的话,用户就会觉得失去了对界面的控制。

1.1 解决单个脚本任务执行时间过长的办法

因为JavaScript线程和UI线程是互斥的,所以我们需要一些办法避免单个脚本占用过多CPU时间:

  1. 首先检查代码是否有死循环,或者递归不能正常推出等情况,一般来说出现这种情况浏览器会提示,但是像在webview和微信小程序中是没有提示的;
  2. 检查循环语句中单任务的执行时间,如果时间过长,那么需要使用setimeoutn个同步任务变成异步任务;
  3. 如果一个函数运行时间过长,也可以把函数任务进行拆分;
  4. CPU密集型任务单独交给worker执行。

二、Ajax

使用Xhr时如何选择postget

  1. get的响应会被缓存,如果需要多次请求统一数据,优先考虑get
  2. 浏览器对get请求的url长度有限制,所以当getsearchParamsurl长度加起来太长时(chrome为4096),需要使用post

2.1 Ajax性能指南

最快的ajax就是没有请求,有两种方法可以避免发送不必要的请求:

  1. 在服务端,通过设置HTTP头来确保响应被缓存;
  2. 在客户端,把获取到的信息主动缓存起来,从而避免再次请求。

2.2 Ajax优化建议

  1. 减少请求数,可以通过合并JavaScriptCSS,对于图片等可以使用MXhr技术;
  2. 合理使用HTTP缓存和客户端缓存;

三、编程实践

3.1 避免双重求值

JavaScript有4种方法可以让我们在程序中提取一个包含代码的字符串,然后动态执行,分别是:evalFunction构造函数、setTimeoutsetInterval。当我们在JavaScript代码中执行另一段JavaScript代码时就会导致双重求值,造成性能损耗。因为每次调用这些方法时都需要重新创建一个新的解释器实例,所以会比直接执行慢得多。

3.2 避免重复性工作

当一个函数被多次调用,并且函数内有重复性工作时,那么它应该被优化,可用的手段有:

  1. 延迟加载,即第一次调用的时候,将重复性工作的结果应用到之后的调用中。
  2. 条件预加载,在第一次调用之前,完成重复性工作内容,并把结果应用到之后的调用中。

3.3 使用速度更快的部分

JavaScript中,位运算要比数学运算和布尔操作快得多,所以有些场景使用位运算会节省大部分时间。举个例子,我们在做表格的斑马条纹时,会通过表格的索引的奇偶来添加相应的类或者样式:

// 数学计算
for (let i = 0; i < len; i++) {
    if (i % 2) {
        className = 'even';
    } else {
        className = 'odd';
    }
}
// 位运算,大约快50%左右
for (let i = 0; i < len; i++) {
    // 奇数的最后一位必定是1,和1的按位与的结果是1
    if (i & 1) {
        className = 'odd';
    } else {
        className = 'even';
    }
}

另外,在JavaScript中做数学运算的时候,尽量使用Math对象,因为这上面的方法是浏览器原生实现的,都是经过编译后的机器码,即使解释器再优化,原生方法的速度必定快于JavaScript代码。

参考文献

[1] 高性能JavaScript Nicolas C. Zakas 著

上一篇下一篇

猜你喜欢

热点阅读