相信写代码对于大部分人都不难,但想写出高性能的代码就需要一定的技术积累啦,下面是一些优化JavaScript代码性能的常见方法。
一.注意作用域
1.避免全局查找
使用全局变量和函数肯定要比局部的开销更大,因为要涉及作用域链上的查找,请看以下函数:
1 function demo1() {
2 var imgs = document.getElementByTagName("img"); //获取页面所有img标签
3
4 for(var i = 0; i <= imgs.length; i++) {
5 imgs[i].title = document.title + "image" + i;
6 }
7 }
上面的代码每执行一次for循环都会在全局寻找document,一旦循环次数很多,那么就严重影响了性能,我们可以在for循环开始之前就把document的引用保存在一个局部变量。改进代码如下:
1 function demo1() {
2 var imgs = document.getElementByTagName("img"); //获取页面所有img标签
3 var doc = document; //局部引用全局变量document
4
5 for(var i = 0; i <= imgs.length; i++) {
6 imgs[i].title = doc.title + "image" + i;
7 }
8 }
二.选择正确方法
1.优化循环
1 for(var i = 0; i <=imgs.length; i++) {
2 //执行代码
3 }
上面代码每次执行循环都会重新计算imgs的长度,一旦循环次数很多,那么积少成多就会影响到代码性能,我们只需在for循环执行之前把imgs的长度保存在一个变量中即可,这样就不用每次都是计算imgs的长度,改进代码如下:
1 var length = imgs.length; //把imgs的长度保存在一个变量中
2 for(var i = 0; i <=length; i++) {
3 //执行代码
4 }
2.尽量使用原生方法
只要有可能,使用原生方法而不是自己用javascript重写一个。原生方法是用诸如c/c++之类的编译型语言写出来的,所以要比JavaScript的快很多很多。
3.使用switch替代if-else
如果有一系列复杂的if-else语句,可以转化成单个switch语句则可以得到更快的代码。还可以通过case语句按照最可能的到最不可能的顺序进行组织,来进行进一步优化switch语句。
三.最小化语句数
1.多个变量申明,javaScript代码中的语句数量也影响所执行的操作的速度,完成多个操作的单个语句要比完成单个操作的多个语句快。
1 //四个语句申明变量,浪费!
2 var name = "Bill";
3 var age = 10;
4 var sex = "man";
5
6 //一个语句申明变量,干的漂亮!
7 var name = "Bill",
8 age = 10,
9 sex = "man";
2.插入迭代值,当使用迭代值(也就是在不同的位置进行增加或减少的值)的时候,尽可能合并语句。
//两个语句,浪费!
var age = values[i];
i++;
//一个语句,干的漂亮!
var age = values[i++];
3.使用数组和对象字面量,你可能看过两种创建数组和对象的方法:使用构造函数或是使用字面量,使用构造函数总是要用到很多语句来插入元素或定义属性,而字面量可以将这些操作在一个语句中完成。
1 //4个语句创建和初始化数组,浪费!
2 var values = new Array();
3 values[0] = 123;
4 values[1] = 456;
5 values[2] = 789;
6
7 //4个语句创建和初始化对象,浪费!
8 var person = new Object();
9 person.name = "Bill";
10 person.age = 10;
11 person.sayName = function () {
12 console.log(this.name);
13 }
14
15 //1个语句创建和初始化数组,干得漂亮!
16 var values = [123, 456, 789];
17
18 //一个语句创建和初始化对象,干的漂亮!
19 var person = {
20 name : "bill",
21 age : 10,
22 sayName : function () {
23 console.log(this.name)
24 }
25 };
26
四.优化DOM交互
1.使用文档碎片减少DOM交互次数,DOM交互越多,性能越慢。
1 var list = document.getElementById("myList"),
2 item,
3 i;
4
5 for (i = 0; i <= 10; i++) {
6 item.document.createElement("li");
7 list.appendChild(item);
8 item.appendChild(document.createTextNode(" Item" + i));
9 }
上面代码每执行一次for循环都会向DOM插入新的元素,一旦for循环次数很多,那么将严重影响代码性能,所以解决办法就是减少DOM交互,于是我们使用createDocumentFragment方法创建虚拟节点,把要插入DOM的元素先插入该虚拟节点,循环完之后再把虚拟节点插入DOM,虚拟节点是不会渲染出来的,只会渲染它的子节点。改进代码如下:
1 var list = document.getElementById("myList");
2 fragment = document.createDocumentFragment(),
3 i;
4
5 for (i = 0; i < 10; i++) {
6 item = document.createElement("li");
7 fragment.appendChild(item);
8 item.appendChild(document.createTextNode("Item" + i));
9 }
10
11 list.appendChild(fragment);
2.使用innerHTML。有两种在页面上创建DOM节点的方法:诸如createElement()和appendChild()之类的DOM方法,以及使用innerHTML。当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JavaScript的DOM调用,由于内部方式是编译好的而非解释执行的,所以执行快的多。
3.使用事件委托,把事件绑定在祖先节点,由于有事件冒泡,当事件触发时根据event对象的target属性可以知道具体事件是在那个子元素发生的。从而执行不同的行为。这样就不必每个子节点都绑定事件。