优化 JavaScript 性能,使它运行足够快,一个关键因素:响应时间
主要包括:下载时间、运行时间、交互响应时间。
JS对响应时间的影响:
1)很大一部分都是由程序员写的 JavaScript 脚本性能不佳所造成的
2)JavaScript 语言本身的性能问题造成
3)其与 DOM 交互时的性能问题
解决方案:
数据访问、作用域链、注意NodeList、repaint/reflow、DOM操作优化、事件委托、节流函数、流程控制、内存泄漏
数据访问优化:
1)合理选择数据类型
直接量<<变量<<数组项<<对象成员 (栈、堆)
2)使用局部变量,它是最快的
缓存频繁使用的对象、数组及相关的属性值
3)避免使用with、try-catch、双重求值
4)减少属性层级
obj.name比obj.xxx.name访问更快,访问属性的速度,与其在对象中的深度有关
'.'操作的次数直接影响着访问对象属性的耗时
var objName = obj.name; //不如缓存起来
NodeList:
遍历NodeList时,不做对当前NodeList相关结构有影响的DOM操作,并且如之前所提到的,要缓存一些频繁使用到的属性值,以避免杯具发生。
优先使用Live NodeList,通过选择器获取以后,再进一步转换成数组来使用。这也是目前许多JS库在使用的方案。
DOM操作优化:
DOM操作优化-先隐藏后显示:
操作DOM前,先把DOM节点删除或隐藏,因为隐藏的节点不会触发重排。
DOM操作优化-一次性修改样式属性:
DOM操作优化-减少读取Layout属性值:
使用缓存,缓存临时节点;
Layout属性值不变:缓存属性值;
Layout属性值变化:截流减少读取;
DOM操作优化-其它:
动画元素考虑采用absolute或fixed
只渲染该元素及子元素,缩小影响范围;
权衡动画速度的平滑
合理选择动画的帧数和时间
不要用tables布局
设置table-layout为auto或fixed,这样可以让table一行一行的渲染
不要在css里面写expression
很多情况下都会触发reflow
使用事件委托
事件委托场景:动态的HTML内容、事件较多、各事件元素共用一个父元素。
1、减少事件绑定,提升性能。2、动态变化的 DOM 结构,仍然可以监听。
流程控制-优化条件判断
1)在if语句中,将经常会发生的条件,放在靠上的位置
2)if的条件为连续的区间时,可以使用二分法的方式来拆分
3)较多离散值的判断,可以使用switch来替代
4)使用数组查询的方式
流程控制-优化循环
一个循环的基本优化步骤如下所示
增值或减值迭代:
大多数循环使用一个从
0
开始、增加到某个特定值的迭代器。在很多情况下,从最大值开始,在循环中不断减值的迭代器更加高效;
简化终止条件:
由于每次循环过程都会计算终止条件,所以必须保证它尽可能快。也就是说避免属性查找或其他操作;
简化循环体:
循环是执行最多的,所以要确保其最大限度地优化,确保其他某些可以被很容易移除循环的密集计算;
使用后测试循环:
最常用
for
循环和
while
循环都是前测试循环。而如
do-while
这种后测试循环,可以避免最初终止条件的计算,因此运行更快;
针对大数据集使用展开循环可以节省很多时间:
内存泄漏-意外的全局变量:
未定义的变量会在全局对象创建一个新变量
use strict严格模式,避免意外的全局变量
全局变量存储大量数据时,确保用完以后把它设置为 null 或者重新定义
内存泄露优化:
总结:
考虑大多数情况,极端情况有能力则兼顾之;
适当取舍“性能与可维护性”权衡之一原则;
站在巨人的肩膀上,看得更远,
前人总结的性能优化方面的经验
好的编程习惯,
不以善小而不为