JS高性能 from《高性能Javascript》

2018-10-29  本文已影响0人  monvhh

总结此书中提到的,写代码需注意,或者可优化的点。
可能不全面。欢迎讨论

加载和执行

Javascript下载和执行
由于浏览器只有一个UI线程,Javascript执行会阻塞UI渲染

1 script标签尽量放在body底部,以减少对整个页面下载的影响。
2 合并多个Javascript文件,减少http请求
3 无阻塞脚本:页面下载完成之后再下载Javascript文件

部分浏览器不支持

加载顺序很重要

4 CDN

数据存取

数据的读取:字面量、本地变量、数组元素、对象成员
1 尽量使用局部变量,如果引用了非局部变量,则在局部缓存该变量,比如var doc=document
2 No eval、new Function这种动态作用域
3 字面量/局部变量的存取速度 > 数组/对象成员的 存取速度
4 嵌套成员 嵌套越深,耗时越多。location.hrefwindow.location.href性能更优

DOM编程

1 JS操作DOM,天生就慢,尽量避免
2 innerHTML vs createElement:差不多,推荐innerHTML
3 克隆DOM element.cloneNode() 略优于 document.createElement()
4 遍历一个HTML collections 比遍历一个数组还要耗时。所以

document.getElementsByName() 等等方式返回的dom节点的类数组对象

5 元素节点: children 优于 childNodes,因为nodes包括注释、空格等等
6 选择器:大量组合查询时,querySelectorAll优于getElementBy...
7 最小化重绘和重排

(1)元素脱离文档流: 隐藏/ 创建dom framgment/ clone
(2) 应用元素改变
(3)将改变后的元素带回文档中: 显示/ append/ innerHTML

8 缓存布局信息,不要频繁获取元素高宽度等信息
9 减少hover,耗费大量CPU计算
10 事件委托:利用冒泡,因为

事件绑定 占用处理时间
浏览器跟踪每个事件处理器,占内存

算法和流程控制

循环

1 No for-in
2 减少查找次数:比如缓存length
3 使用倒序,因为终止条件非0为真,而正序时<length,比较是两次,先判断大小,再判断真假。
4 减少迭代次数:“Duff's Device’”

while(i){
  process(items[i--]);
  process(items[i--]);
  process(items[i--]);
  process(items[i--]);
  ...
}

5 基于函数的迭代(eg.Array.forEach)不如loops(eg.for

条件语句

1 条件多时用switch(vs if-else
2 最可能出现条件放在最前面
3 使用嵌套if-else,而不是链式

像二分法一样,逐步缩小范围
4 大量离散值,使用查找表,即对象或数组,明确的对应关系
连续分块的,可能3更合适

递归

1 堆栈溢出一般都是因为不正确的终止条件
2 优化为尾递归,因为es6有尾递归优化
3 递归 改为 迭代实现
4 缓存遍历中的结果,避免重复遍历

字符串和正则表达式

字符串

1 str = str + "one" + "two"优于str+="one";str+="two";优于str+="one"+"two"

第一种最优的原因是浏览器内存分配的优化,不一定所有浏览器都适用
部分浏览器可能会在编译期就对"one"+"two"进行合并了。

2 数组项合并Array.join()耗时大于字符串拼接

IE7反之

3 string.concat+ +=耗时多

正则表达式

1 具体化,能多具体写多具体,减少匹配失败成本和回溯
2 原子组,Javascript中可以用预查 (?=)
3 尽量避免嵌套量词:减少回溯
4 确保正则表达式的两个部分不能对字符串的相同部分进行匹配:减少回溯
5 以简单、必须的字元开始
6 字元互斥,同4
7 减少分支数量,缩小分支范围:比如red|raw -> r(?:ed|aw)
8 使用非捕获组:捕获组消耗时间和内存来记录反向引用,不需要反向引用的就可以避免
9 补充8,只捕获感兴趣的文本以减少后处理
10 暴露必须的字元,同1
11 合适的量词,减少回溯
12 将正则表达式赋值给变量并重用它们:主要是防止循环体重重复编译正则表达式
13 拆分复杂正则表达式
14 能简单通过字符串的方法实现就不要用正则
15 去除首尾空白的例子,非常经典具体,最后混合使用字符串方法和正则达到性能最优

快速响应用户界面

解决脚本执行阻塞用户界面更新
记录耗时,针对性的解决

1 使用定时器让出时间片段:需要限制定时器数量,否则性能更差
2 分割任务
3 web worker

Ajax

1 利用Beacons,无需response。

new image().src=url+'?'+params.join('&') ,google、百度 analysis好像都是这么做的

2 缓存:客户端和服务端

3 合并请求,减少请求数

其他

1 使用Object Array 直接量
2 避免重复工作
3 LazyLoading
4 条件预加载,调用更快。与3正相反,适用不同的场景
5 位操作性能更优,比如取模可以用位操作
6 原生方法 性能更优

上一篇下一篇

猜你喜欢

热点阅读