2. DOM 操作应该是脚本中最耗性能的一类操作, 避免频繁的操作 Dom 元素, 例如增加, 修改, 删除 DOM 元素或者对 DOM 集合进行操作, 如果脚本中包含了大量的 DOM 操作则需要注意以下几点:
a.html Collection(HTML 收集器, 返回的是一个数组内容信息)
在脚本中 document.images,document.forms ,getElementsByTagName() 返回的都是 HTMLCollection 类型的集合, 在平时使用的时候大多将它作为数组来使用, 因为它有 length 属性, 也可以使用索引访问每一个元素. 不过在访问性能上则比数组要差很多, 原因是这个集合并不是一个静态的结果, 它表示的仅仅是一个特定的查询, 每次访问该集合时都会重新执行这个查询从而更新查询结果. 所谓的 "访问集合" 包括读取集合的 length 属性, 访问集合中的元素.
因此, 当你需要遍历 HTML Collection 的时候, 尽量将它转为数组后再访问, 以提高性能. 即使不转换为数组, 也请尽可能少的访问它, 例如在遍历的时候可以将 length 属性, 成员保存到局部变量后再使用局部变量.
b. Reflow & Repaint
除了上面一点之外, DOM 操作还需要考虑浏览器的 Reflow 和 Repaint , 因为这些都是需要消耗资源的, 具体的可以参加以下文章:
如何减少浏览器的 repaint 和 reflow?
Understanding Internet Explorer Rendering Behaviour
Notes on HTML Reflow
3. 慎用 with
with(obj){ p = 1}; 代码块的行为实际上是修改了代码块中的 执行环境 , 将 obj 放在了其作用域链的最前端, 在 with 代码块中访问非局部变量是都是先从 obj 上开始查找, 如果没有再依次按作用域链向上查找, 因此使用 with 相当于增加了作用域链长度. 而每次查找作用域链都是要消耗时间的, 过长的作用域链会导致查找性能下降.
因此, 除非你能肯定在 with 代码中只访问 obj 中的属性, 否则慎用 with, 替代的可以使用局部变量缓存需要访问的属性.
4. 避免使用 eval 和 Function
每次 eval 或 Function 构造函数作用于字符串表示的源代码时, 脚本引擎都需要将源代码转换成可执行代码. 这是很消耗资源的操作 -- 通常比简单的函数调用慢 100 倍以上.
eval 函数效率特别低, 由于事先无法知晓传给 eval 的字符串中的内容, eval 在其上下文中解释要处理的代码, 也就是说编译器无法优化上下文, 因此只能有浏览器在运行时解释代码. 这对性能影响很大.
Function 构造函数比 eval 略好, 因为使用此代码不会影响周围代码 ; 但其速度仍很慢.
此外, 使用 eval 和 Function 也不利于 Javascript 压缩工具执行压缩.
5. 减少作用域链查找 (这方面设计到一些内容的相关问题)
前文谈到了作用域链查找问题, 这一点在循环中是尤其需要注意的问题. 如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量, 并在遍历结束后再重写那个变量, 这一点对全局变量尤其重要, 因为全局变量处于作用域链的最顶端, 访问时的查找次数是最多的. 举个栗子:
- // 低效率的写法:
- var globalVar = 1; // 全局变量
- function myCallback(info){
- for( var i = 100000; i--;){
- // 每次访问 globalVar 都需要查找到作用域链最顶端, 本例中需要访问 100000 次
- globalVar += i;
- }
- }
- // 更高效的写法:
- var globalVar = 1; // 全局变量
- function myCallback(info){
- // 局部变量缓存全局变量
- var localVar = globalVar;
- for( var i = 100000; i--;){
- // 访问局部变量是最快的
- localVar += i;
- }
- // 本例中只需要访问 2 次全局变量
在函数中只需要将 globalVar 中内容的值赋给 localVar
- globalVar = localVar;
- }
此外, 要减少作用域链查找还应该减少闭包的使用.
6. 数据访问
Javascript 中的数据访问包括直接量 (字符串, 正则表达式 ), 变量, 对象属性以及数组, 其中对直接量和局部变量的访问是最快的, 对对象属性以及数组的访问需要更大的开销. 当出现以下情况时, 建议将数据放入局部变量:
a. 对任何对象属性的访问超过 1 次
b. 对任何数组成员的访问次数超过 1 次
另外, 还应当尽可能的减少对对象以及数组深度查找.
7. 字符串拼接
在 Javascript 中使用 "+" 号来拼接字符串效率是比较低的, 因为每次运行都会开辟新的内存并生成新的字符串变量, 然后将拼接结果赋值给新变量. 与之相比更为高效的做法是使用数组的 join 方法, 即将需要拼接的字符串放在数组中最后调用其 join 方法得到结果. 不过由于使用数组也有一定的开销, 因此当需要拼接的字符串较多的时候可以考虑用此方法.
来源: http://www.qdfuns.com/article/33760/c4ae4a5f4794df0ef12d5ee02a073913.html