相信写代码对于大部分人都不难,但想写出高性能的代码就需要一定的技术积累啦,下面是一些优化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属性可以知道具体事件是在那个子元素发生的。从而执行不同的行为。这样就不必每个子节点都绑定事件。