随着作用域中的作用域数量的增加,访问当前作用域以外的变量的时间也在增加。所以访问全局变量总是比访问局部变量要慢,因为需要遍历作用域链。只要能减少花费在作用域链上的时间,就能增加脚本的整体性能。
所以尽量避免多次的全局查找(因为要逐层向上的作用域进行查找)
这个函数的时间复杂度是 (循环次数 * 查找到 document.title属性) 的次数,查找到 title 最坏的情况是遍历 document 的所有属性,最后才查找到 title 属性,而且每一次查找document都要进行多层的,逐层向上的作用域查找
优化前
function test() {
var imgs = document.getElementByTagName("img");
for(var i = 0, len = imgs.length; i < len; i++) {
imgs[i].title = document.title + " image " + i;
}
}
优化后
function test() {
var title = document.title;
var imgs = doc.getElementByTagName("img");
for(var i = 0, len = imgs.length; i < len; i++) {
imgs[i].title = title + " image " + i;
}
}
JS中访问变量或者数组都是 O(1) 操作,比访问对象上的属性更有效率,访问对象的属性的是一个 O(n) 的操作,最坏的情况是查找对象所有的属性后,才查找到。对象的任何属性查找要比访问变量花费更长的时间,因为必须在原型链中对拥有该名称的属性进行一次搜索,即属性查找越多,执行时间越长。所以针对需要多次用到的对象属性,应将其存储在局部变量,或者使用对象解构的方式存储起来。
这个函数在优化前的时间复杂度是 O(100 * n) ,因为一共 100 次循环,每次循环的时候都要去查找An属性,每次查找An属性都要遍历n次
优化前
let data = {
A1: 1,
A2: 2,
A3: 3
...
An: 100
}
function test(data) {
for(let i = 0; i < 100; ++i) {
console.log(data.An);
}
}
test(data);
优化后
let data = {
A1: 1,
A2: 2,
A3: 3
...
An: 100
}
function test({A1, A2, A3...An}) {
function test(data) {
for(let i = 0; i < 100; ++i) {
console.log(An);
}
}
test(data);
优化后的时间复杂度就只为 O(100) 了,不需要每次循环中都去查找 An 属性的值,而是使用局部变量进行了存储。
循环是编程中最常见的结构,优化循环是性能优化过程中很重要的一部分。一个循环的基本优化步骤如下:
减值迭代——大多数循环使用一个从0开始,增加到某个特定值的迭代器。在很多情况下,从最大值开始,在循环中不断减值的迭代器更加有效。
简化终止条件——由于每次循环过程都会计算终止条件,故必须保证它尽可能快,即避免属性查找或其它 O(n) 的操作。
简化循环体——循环体是执行最多的,故要确保其被最大限度地优化。确保没有某些可以被很容易移出循环的密集计算。
(1) switch语句较快——若有一系列复杂的if-else语句,可以转换成单个switch语句则可以得到更快的代码,还可以通过将case语句按照最可能的到最不可能的顺序进行组织,来进一步优化。
(2) 位运算较快——当进行数学运算时,位运算操作要比任何布尔运算或算数运算快。选择性地用位运算替换算数运算可以极大提升复杂计算的性能,诸如取模,逻辑与和逻辑或也可以考虑用位运算来替换。
(3) 字符串拼接,在 JS 中使用 “+” 号来拼接字符串效率是比较低的,因为每次运行都会开辟新的内存并生成新的字符串变量,然后将拼接结果赋值给新变量。与之相比更为高效的做法是使用 join 方法,因此当需要拼接的字符串较多的时候可以考虑用此方法。更提倡使用es6中的字符串模板,更加的快速高效。当然如果只是几个或者几十个字符串的拼接,那么使用哪种方法在性能上的区别都不大。
(4) 使用直接量,在某些浏览器上对象创建比直接量要耗时很多
var aTest = new Array(); //替换为
var aTest = [];
var aTest = new Object; //替换为
var aTest = {};
var reg = new RegExp(); //替换为
var reg = /../;
//如果要创建具有一些特性的一般对象,也可以使用字面量,如下:
var oFruit = new O;
oFruit.color = "red";
oFruit.name = "apple";
//前面的代码可用对象字面量来改写成这样:
var oFruit = { color: "red", name: "apple" };
(5) 最小化语句数
JS代码中的语句数量也会影响所执行的操作的速度,完成多个操作的单个语句要比完成单个操作的多个语句块快。故要找出可以组合在一起的语句,以减来整体的执行时间。这里列举几种模式
优化前
var i = 1;
var j = "hello";
var arr = [1,2,3];
var now = new Date();
优化后
var i = 1,
j = "hello",
arr = [1,2,3],
now = new Date();
优化前
var name = values[i];
i++;
优化后
var name = values[i++];
优化前
var a = new Array();
a[0] = 1;
a[1] = "hello";
a[2] = 45;
var o = new Obejct();
o.name = "bill";
o.age = 13;
优化后
var a = [1, "hello", 45];
var o = {
name : "bill",
age : 13
};