JS代码优化

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值