高性能 JavaScript

Javascript

最近翻看了泽卡斯的《高性能JavaScript》,受益颇深,就顺手记录了下读后感

模块 1 加载

使用加载而不是引入的形式来处理外部的JS文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";

if (script.readyState) { //IE浏览器下
script.onreadystatechange = function() {
if (script.readyState == "loaded" || "complete") {
script.onreadystatechange = null;
callback();
}
}

} else { //chrome FireFox...
script.onload = function() {
callback();
}
}

script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}

模块 2 数据访问

直接量 > 变量 > 数组 > 对象 (访问速度由高到低)

对于每种类型,又有 局部变量 > 全局变量

对于不同类型的数据,浏览器处理起来的速度是有所差异的。
了解了它们的访问速度排名,在编写JavaScript时便多了一份随手优化性能的意识

1
2
3
4
5
6
var i = 0;

//不好的写法
for(i = 0; i < document.getElementsByTagName('li').length; i++) {
// dosomething
}

上面的代码中每次for循环都需要访问document这个全局变量,而且还得访问并计算li的长度,看起来相当繁琐,也耗费性能。
分析一下便知道,document.getElementsByTagName(‘li’)在循环中访问次数较高,可先用一个变量将其存放起来(如下)

1
2
3
4
5
6
var i = 0;
var li = document.getElementsByTagName('li');
//较好的写法
for(i = 0; i < li.length; i++) {
//dosomething
}

如果深究下去还会发现,length在循环中仅仅相当于一个常量,把li的length直接赋值给某个变量效果更好(这取决于你的循环中是否还需调用li这个对象)。

1
2
3
4
5

//推荐的写法
for(var i = 0, length = var li = document.getElementsByTagName('li'); i < li.length; i++) {
//dosomething
}

透过小例子看大项目,这感觉不赖吧。关于JavaScript还有一些其他的小秘密,我们继续上菜

模块 3 DOM编程

1) 重绘与重排的开销问题

对于重绘和重排大家应该不陌生,DOM操作往往成为一个项目性能的瓶颈。
相对于Object、Array操作,DOM的访问开销直接升上了几个量级,这还不包括随后的修改DOM。
对于浏览器,渲染出一颗DOM树通常是在对html遍历了一次之后(table需要多次),这是一件很吃力的事情。以下是几个引起浏览器的重排:
a DOM元素的几何属性变化
b DOM树的结构变化
c 获取某些属性时(别惊讶)

2) 修改DOM操作

削减DOM操作看起来是件重要的事情,对于无法避免的时候,在操作DOM时就得花些心思了:
第一步,先使元素脱离文档流
第二步,对其应用多重改变
最后, 再将其带回文档中。

3) IE 和 :hover

4) 事件绑定转为事件委托

~

模块 4 算法

1) for的倒序输出, 达夫设备

2) 查找表 > switch > if else > foreach

~

模块 5 界面响应

单个JS回应用户,应在100ms内完成

以上为笔记