您的位置:首页 > Web前端 > JavaScript

JS代码优化

2017-09-08 15:03 169 查看

1.注意作用域

(1)避免全局查找:

将在一个函数中会用到多次的全局对象存储为局部变量总是没错的。

function updateUI(){
var imgs = document.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].title = document.title + " image " + i;
}
//........
}
// 函数有两次对全局对象document对象的引用。如果页面上有多个图片,
// 那么for循环中document引用就会被执行多次,每次都要进行作用域链的查找


function updateUI(){
var doc = document;
var imgs = doc.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].title = doc.title + " image " + i;
}
//........
}
// 为了优化代码,可以通过创建一个局部变量指向document对象,
// 就可以通过限制一次全局查找来优化这个函数的性能


(2)避免with语句

和函数类似,with语句会创建自己的作用域,因此会增加其中执行代码的作用域的长度。由于额外的作用域链查找,在with语句中执行的代码肯定比外面执行的代码慢。

function updateUI(){
with(document.body){
alert(tagName);
innerHTML = "hello";
}
}


应该改为:

function updateUI(){
var body = document.body;
alert(body.tagName);
body.innerHTML = "hello";
}


原因:标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止。

总结:访问全局变量总要比访问局部变量慢,因为需要遍历作用域链。只要能减少花费在作用域链上的时间,就能增加脚本的整体性能。

2.选择正确方法

(1)避免不必要的属性查找

例如:

var query = window.location.href.substring(window.location.href.indexOf("?"));


上述语句,进行了6次属性查找

应该改为,进行了4次属性查找,比原始版本节省33%的属性查找时间。
var url = window.location.href;
var query = url.substring(url.indexOf("?"));

总结:只要能减少算法的复杂度,就要尽可能减少。尽可能多地使用局部变量将属性查找替换为值查找。进一步讲,如果可以用数字化的数组位置进行访问,也可以用命名属性,那么使用数字位置。

(2)优化循环

①减值迭代

for (var i = 0; i < array.length; i++) {
fn(array[i]);
}
每次循环i都会与array.length进行比较,涉及属性查找,时间复杂度O(n)

for (var i = array.length-1; i >=0; i--) {
fn(array[i]);
}
改为与常数0比较,时间复杂度变为O(1)

②简化终止条件

由于每次循环过程都会计算终止条件,所以必须保证它尽可能快,也就是避免属性查找以及其他O(n)操作

上述例子改为减值迭代,但如果函数内的数据处理与顺序有关,无法使用减值迭代,则应优化为

for (var i = 0,len=array.length; i < len; i++) {
fn(array[i]);
}


那么前面提到的避免全局查找的例子也可以再进一步优化终止条件

function updateUI(){
var doc = document;
var imgs = doc.getElementsByTagName('img');
for (var i = 0,len=imgs.length; i < len; i++) {
imgs[i].title = doc.title + " image " + i;
}
//........
}
// 为了优化代码,可以通过创建一个局部变量指向document对象,
// 就可以通过限制一次全局查找来优化这个函数的性能


③简化循环体

循环体执行最多,确保最大限度被优化,确保没有某些可以很容易被移出循环体的密集计算。

④使用后测试循环

for循环,while循环属于前测试循环。而do-while属于后测试循环,可以避免最初终止条件的计算,因此运行更快、

(3)展开循环

当循环的次数确定,消除循环并多次使用函数调用往往更快。

for (var i = 0; i < 3; i++) {
fn(array[i]);
}

fn(array[0]);
fn(array[1]);
fn(array[2]);


第二种方法比第一种更快

(4)避免双重解释

尽可能避免出现需要按照javascript解析的字符串

例如

eval("alert('hello!')");
var fn = new Function("alert('hello!')");
setTimeout("alert('hello!')",500);


(5)原生方法较快

(6)Switch语句较快

(7)位运算符较快

3.最小化语句数

(1)多个变量声明合并成一条语句

var a = 1;
var b = 5;
var c = "red";


应该优化为

var a = 1,
b = 5,
c = "red";


(2)插入迭代值

var age = person[i];
i++;
应该优化为
var age = person[i++];


(3)使用数组和对象字面量

var arr = new Array();
arr[0] = 1;
arr[1] = 50;
arr[2] = 7;
应该优化为
var arr = [1,50,4];

var obj = new Object();
obj.name = "Jack";
obj.age = 27;
obj.sayName = function(){
return this.name;
}
应该优化为
var obj = {
name:"Jack",
age:27,
sayName:function(){
return(this.name);
}
};


4.优化DOM交互

(1)最小化现场更新

(2)使用innerHTML

(3)使用事件代理

(4)注意HTMLCollection

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: