js性能优化小结
避免全局查找
浏览器访问局部变量的速度要比访问全局变量的速度更快,变量在作用域链中一层一层查找需要消耗时间。
1 // 不推荐 2 function fn(){ 3 document.getElementById('id1'); 4 document.getElementById('id2'); 5 } 6 7 // 推荐 8 function fn(){ 9 var doc = document; 10 doc.getElementById('id1'); 11 doc.getElementById('id2'); 12 } 13 // 推荐 14 !function fn(doc){ 15 doc.getElementById('id1'); 16 doc.getElementById('id2'); 17 }(document);
类似eval的问题
js中的eval、setTimeout、setInterval、new Function()操作都能将字符串当作js代码来执行,在此过程中代码执行效率非常底下,应当避免使用。推荐使用匿名函数或传递函数引用。
1 // 不推荐使用eval 2 3 // setTimeout、setInterval、new Function建议直接传入匿名函数或函数引用 4 setTimeout('alert(1)', 1000); // 不推荐 5 setInterval('alert(1)', 1000); // 不推荐 6 var oFn = new Function('alert(1)'); // 不推荐 7 8 // 推荐 9 setTimeout(function(){ 10 alert(1); 11 }, 1000); 12 setTimeout(fn, 1000); 13 14 setInterval(function(){ 15 alert(1); 16 }, 1000); 17 //setInterval(fn, 1000); 18 19 var oFn = new Function(function(){ 20 alert(1); 21 }); 22 var oFn = new Function(fn); 23 24 function fn(){ 25 alert(1); 26 }
定时器
当不断间隔一段时间运行代码时,应当使用setInterval,而不要通过setTimeout来实现,因为开启一个定时器都会初始化一次,采用setTimeout是通过不断初始化定时器来实现的。
1 var i = 0, 2 timer = null; 3 4 // 不推荐 5 function fnTimeout(){ 6 if(i < 10){ 7 setTimeout(fnTimeout, 1000); // 不断初始化 8 } 9 console.log(i++); 10 } 11 fnTimeout(); 12 13 // 推荐 14 function fnInterval(){ 15 if(i >= 10){ 16 clearInterval(timer); 17 timer = null; 18 } 19 console.log(i++); 20 } 21 setInterval(fnInterval, 1000); // 初始化一次
多个字符串连接
如果需要将多个字符串连接起来,要少使用+=,最好使用数据的jolin方法。
1 var a = 'a', 2 b = 'b', 3 c = 'c', 4 s = '', 5 arr = []; 6 7 // 不推荐 8 s += a; 9 s += b; 10 s += c; 11 12 // 推荐 13 s = a + b + c; 14 15 // 最佳 16 arr.push(a); 17 arr.push(b); 18 arr.push(c); 19 s = arr.join('');
类型转换
将数字转换为字符串使用"" + 数字 ;
字符串转数字:1*字符串;
任何内型转布尔:!!变量;
变量声明使用单var
变量声明都采用单var形式,可以减少代码执行时间,变量声明比较统一。
1 // 不推荐 2 var a = 'a'; 3 var b = 'b'; 4 var c = 'c'; 5 var s = ''; 6 var arr = []; 7 8 // 推荐 9 var a = 'a', 10 b = 'b', 11 c = 'c', 12 s = '', 13 arr = [];
自增自减放入表达式中
1 // 不推荐 2 var i = 0, 3 b = i; 4 i++; 5 6 // 推荐 7 var i = 0, 8 b = i++;
使用对象和数组字面量
1 // 不推荐 2 var arr = new Array, 3 obj = new Object, 4 re = new RegExp('a'); 5 6 // 推荐 7 var arr = [], 8 obj = {}, 9 re = /a/;
闭包中不再使用的变量的释放
闭包中的变量如果有其他函数使用了,那么该变量一直会留在内存中,另外DOM的引用会消耗很大的内存,因此应该及时释放闭包中不再引用的变量。
1 // 不推荐 2 var fn = !function(doc){ 3 var obj = {name: 'hum'}, 4 arr = [1, 2], 5 oDom = doc.getElementById('id'); 6 7 // ...... 8 9 return function(){ 10 console.log(obj.name); 11 } 12 }(document); 13 14 // 推荐 15 var fn = !function(doc){ 16 var obj = {name: 'hum'}, 17 arr = [1, 2], 18 oDom = doc.getElementById('id'); 19 20 // ...... 21 22 arr = doc = oDom = null; // 释放 23 24 return function(){ 25 console.log(obj.name); 26 } 27 }(document);
减少reflow
在css规范中有一个渲染对象的概念,通常用盒子来表示。mozilla通过一个叫frame的对象来操作盒子。
reflow:加载DOM树、创建或更新frame结构的响应 的过程。减少reflow的方法:
1、将元素删除,完成修改后还原
2、将元素display等于none,完成修改后还原
3、修改多个样式时用类代替对此style操作
4、添加大量元素到页面使用documentFragment
事件委托
将子元素的事件都注册到父元素或更高的元素上,不用为每个子节点注册事件监听。
DOM删除
删除DOM节点时,一定要删除DOM上绑定的事件,否则无法回收,占用内存。
减少DOM集合的访问
通过js获取集合的情况:
1、getElementsByTagName
2、childNodes
3、attributes
4、document.forms document.images
...
缩短否定操作
尽量使用逻辑非来进行条件判断,而减少使用等于null或等于false