可能优化脚本性能最重要的就是注意全局查找。使用全局变量和函数肯定要比局部的开销更大,因为要涉及作用域链上的查找。将在一个函数中会用到多次的全局对象存储为局部变量总是没错的。 特别是使用链式操作的时候,如果涉及到全局变量,应把全局变量赋予给局部变量
在性能非常重要的地方必须避免使用 with 语句。和函数类似,with 语句会创建自己的作用域,因此会增加其中执行的代码的作用域链的长度。由于额外的作用域链查找,在 with 语句中执行的代码肯定会比外面执行的代码要慢。
一般来讲,只要能减少算法的复杂度,就要尽可能减少。尽可能多地使用局部变量将属性查找替换为值查找。进一步讲,如果即可以用数字化的数组位置进行访问,也可以使用命名属性(诸如 NodeList对象),那么使用数字位置。
循环是编程中最常见的结构,在JavaScript程序中同样随处可见。优化循环是性能优化过程中很重要的一个部分,由于它们会反复运行同一段代码,从而自动地增加执行时间。在其他语言中对于循环优化有大量研究,这些技术也可以应用于 JavaScript。一个循环的基本优化步骤如下所示。
Duff 装置的基本概念是通过计算迭代的次数是否为8的倍数将一个循环展开为一系列语句。
示例:
//假设 values.length > 0
var iterations = Math.ceil(values.length / 8);
var startAt = values.length % 8;
var i = 0;
do {
switch(startAt){
case 0: process(values[i++]);
case 7: process(values[i++]);
case 6: process(values[i++]);
case 5: process(values[i++]);
case 4: process(values[i++]);
case 3: process(values[i++]);
case 2: process(values[i++]);
case 1: process(values[i++]);
}
startAt = 0;
} while (--iterations > 0);
更快的实现方法
//credit: Speed Up Your Site (New Riders, 2003)
var iterations = Math.floor(values.length / 8);
var leftover = values.length % 8;
var i = 0;
if (leftover > 0){
do {
process(values[i++]);
} while (--leftover > 0);
}
do {
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
} while (--iterations > 0);
示例:
//4 个语句——很浪费
var count = 5;
var color = "blue";
var values = [1,2,3];
var now = new Date();
优化后:
//一个语句
var count = 5,
color = "blue",
values = [1,2,3],
now = new Date();
尽可能使用数组和对象字面量