Js极客之路 - 优化操作(性能优化)
1.因为每次For循环都会计算一次arr.length,所以有必要存储数组长度以减少计算。针对这篇文章(http://www.crimx.com/2015/04/21/should-array-length-be-cached-or-not/),V8引擎好像已经帮我们做了不变数据的缓存,不过个人认为还是很有必要的,像他说的,假若只有V8引擎做了此事(V8开发者有这样说吗?),我们做缓存,对于V8就当帮它咯,对于其他就是优化咯。
//bad
var arr=[1,2,3,...];
for(var i=0; i<arr.length; i++){
...code
}
//good
var arr=[1,2,3,...],
len=arr.length,
i=0;
for(; i<len; i++){
...code
}
2.将字符串转变成数字的几种方法。
//第一种:
var a='12';
console.log(typeof a); //string
a=parseInt(a); //parseInt()、Math.floor()等
console.log(typeof a); //number
//第二种:
var a='12';
a=a-0; //-、*、/等
console.log(typeof a); //number
//第三种(参考地址-http://www.w3school.com.cn/js/pro_js_operators_unary.asp):
var a='12';
a = +a ; //+、-、~等
console.log(typeof a); //number
//第四种:
var a='12';
a = a >> 0 ; //>>、>>>等
console.log(typeof a); //number
听说第二种和第三种是性能快点,或许可以参照《将数字转变成字符串的几种方法》下别人的话。
第四种:按位操作是在数值表示的最底层执行操作,因此速度更快。计算过程参考:
①:https://msdn.microsoft.com/zh-cn/library/5s9e947e(v=vs.94).aspx
②:http://zhidao.baidu.com/link?url=lHM_2XsAX2N3zmaDwhA8IUivdkjhBO-9RLYg-qLRfTuh7qo2wJYaEZXi5mlu4VWPMSNtBL404448uJBxrrfK_Y-E4WDdhSgg31ofHAj72nC
3.将数字转变成字符串的几种方法。
//第一种:
var a=100;
console.log(typeof a); //number
a=a.toString(); //toString()、toFixed()等
console.log(typeof a); //string
//第二种:
var a=100;
a=''+a;
console.log(typeof a); //string
别人的话:从性能上来看,将数字转换成字符时,有如下公式:("" +) > String() > .toString() > new String()。String()属于内部函数,所以速度很快。而.toString()要查询原型中的函数,所以速度逊色一些,new String()需要重新创建一个字符串对象,速度最慢。
4.选择作用域链最短的方法:Javascript的变量采用链式作用域;读取变量的时候,先在当前作用域寻找该变量,如果找不到,就前往上一层的作用域寻找该变量;这样的设计,使得读取局部变量比读取全局变量快得多。
//bad,假设num只在a函数里被使用
var num=10;
function a(){
num++;
...code
}
a();
//good
function a(){
var num=10;
num++;
...code
}
a();
5.多个if-else执行的时候,其会顺序检索每一个条件,直到所有条件检索完或检索到匹配的条件,所以我们可以通过树的形式组织if语句(正常人应该不会这样做)。
//bad?
if(con === 1) {return result1;}
else if(con === 2) {return result2;}
else if(con === 3) {return result3;}
else if(con === 4) {return result4;}
else if(con === 5) {return result5;}
else if(con === 6) {return result6;}
else if(con === 7) {return result7;}
else if(con === 8) {return result8;}
else if(con === 9) {return result9;}
这段代码就会依次判断con是否等于1,2,3,4,5,6,7,8,9,如果是9的话,就会判断9次。
//good?
if (con <= 3){
if(con === 1) {return result1;}
else if(con === 2) {return result2;}
else {return result3;}
} else if(con > 3 && con <= 6){
if(con === 4) {return result4;}
else if(con === 5) {return result5;}
else {return result6;}
} else if(con <= 9){
if(con === 7) {return result7;}
else if(con === 8) {return result8;}
else {return result9;}
}
这样我们通过三叉树的形式,就可以减少查找次数了,比如这里查找9次,分别判断 0~3,3~6,6~9,7,8,9,只需要6次。
if-else除了通过这种树形组织编码以外,还有一个优化的地方。由于其顺序判断的逻辑,我们可以根据概率来,将概率比较大的判断放在前面,概率较小的放在后面,这样也可以减少平均查找长度(这个才是人可以做的)。
6.不要在循环体中包含函数表达式,事先将函数提取到循环体外。因为循环体中的函数表达式,运行过程中会生成循环次数个函数对象。这个跟【1】是一样的道理。
// good function clicker() { // ...... } for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; addListener(element, 'click', clicker); } // bad for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; addListener(element, 'click', function () {}); }
7.ECMAScript 5方法的使用。
ES5提供了很多新的方法,虽然老式的浏览器不支持,但现在都是HTML5时代了,所以能用ES5的方法的时候就大胆的用;有句话好像说的好:浏览器自带的方法怎么都比你用js写出来的方法高效,因为它用的更加底层的语言写的。
DOM优化:
1.使用DocumentFragment优化多次append?
也许对于老的浏览器有效(http://ejohn.org/blog/dom-documentfragments/),但是现代浏览器都优化的很好了,所以此方式已显得不为重要,过时(http://www.zhihu.com/question/30498056#answer-14749261)。
2.使用一次innerHTML赋值代替多次向DOM结构里添加新节点,减少DOM与JS的交互。
//bad
for(var i=0; i<1000; i++){
var elem=document.createElement('p');
elem.innerHTML=i;
document.body.appendChild( elem );
}
//good
var html=[],
i=0;
for(; i<1000; i++){
html.push( '<p>'+i+'</p>' )
}
document.body.innerHTML+=html.join('');
3.减少回流或重绘(http://www.css88.com/archives/4996)。
▊ 使用更改className的方式替换style.xxx=xxx的方式。
▊ 使用style.cssText = '';一次写入样式。
//bad
var oDiv=document.getElementById('test');
oDiv.onclick=function(){
this.style.background='red';
this.style.fontSize='12px';
this.style.border='1px solid #ccc';
}
//good
var oDiv=document.getElementById('test');
oDiv.onclick=function(){
this.className='xxx'
}
或者
oDiv.onclick=function(){
this.style.cssText='background: red; font-size: 12px; border: 1px solid #ccc;'
}
4.使用事件委托的方式替代给每个元素添加事件,既可以减少子元素的事件绑定,动态添加的元素又相当于获得了相应的事件。
例:页面有一个div(id="wrap"),div下面有100个span,现在需求是点击每个span,弹出span里的文本内容。
//bad
var aSpan=document.getElementById('wrap').getElementsByTagName('span'),
len=aSpan.length,
i=0;
for(; i<len; i++){
aSpan[i].onclick=function(){
alert( this.textContent )
}
}
//good
document.getElementById('wrap').onclick=function(e){
alert( e.target.textContent )
}
SVG优化:
1.给组添加样式替代给多个子元素添加样式(引:这是一种无损优化,既可以减少文件大小又可以提高渲染速度)。
//bad
<rect width="20" height="20" fill="#F15C80" ></rect>
<circle cx="40" cy="10" r="10" fill="#F15C80" ></circle>
...more
//good
<g fill="#F15C80">
<rect width="20" height="20" ></rect>
<circle cx="40" cy="10" r="10" ></circle>
...more
</g>
2.缩小精度(引:过度的准确性常见于自动生成的SVG文件中,缩放小数精度的优化效果是显而易见的,但是除去1位小数是对于文件而言是没有太大区别的。这是一个有损耗的方法来减少文件大小,加快加载速度),这个对于画图其实是有必要的,计算值往往小数位很多,而实际为了让图形显示得不模糊,我们会取整后±0.5。
//bad
<path d="M165.381249999999994 -.5v400" stroke="#90ED7D" stroke-width="1.2"></path>
//good
<path d="M165.5 -.5v400" stroke="#90ED7D" stroke-width="1.2"></path>
3.创建SVG DOM元素时先设置其样式,再将其添加到父级。因为FF(开发者版本好像可以),IE不支持innerHTML添加的SVG DOM元素,所以只能用appendChild添加,此时先设置样式可以减少回流或重绘。
//bad
var oRect=document.createElementNS('http://www.w3.org/2000/svg','rect');
oSvg.appendChild(oRect);
oRect.setAttribute('width',30);
oRect.setAttribute('height',30);
//good
var oRect=document.createElementNS('http://www.w3.org/2000/svg','rect');
oRect.setAttribute('width',30);
oRect.setAttribute('height',30);
oSvg.appendChild(oRect);
jQuery优化:
1.缓存重复使用的jQuery对象减少查询。
//bad
var oP=$('#test').find('p'),
oEm=$('#test').find('em');
//good
var oBox=$('#test'),
oP=oBox.find('p'),
oEm=oBox.find('em');
2.jQuery最佳实践:http://www.ruanyifeng.com/blog/2011/08/jquery_best_practices.html
逻辑优化:
1.函数节流,减少事件交互次数(学习地址->http://www.alloyteam.com/2012/11/javascript-throttle/)。
2.单例模式(学习地址->http://www.alloyteam.com/2012/10/common-javascript-design-patterns/)。
3.Ajax缓存。
4.具体场景具体分析。
性能优化总结:
以上内容基本是经过测试,或者说得很有道理(不知道该怎么测试),期待指正,教导。
性能优化,对于一些小程序或者高配置来说几乎用肉眼是感受不到的,但是对于大数据可视化、低配置、热爱极致完美的人来说,优化还是非常必要的,Perfect的感觉非“强迫症”的人不懂!
对于类似A && B || C 与 A ? B : C【还比如 arr.length 与 arr[0] 判断数组为空】 谁的效率更高这样的问题,做为正常人就不要去纠结咯(原文地址->http://www.zhihu.com/question/20293486):
不同的浏览器解析方式未必相同,所以:适合自己的才是最好的。
参考:
http://www.codeceo.com/article/javascript-guide.html
http://www.csdn.net/article/2015-01-27/2823722
http://segmentfault.com/a/1190000000490326#articleHeader31
https://github.com/ecomfe/spec/blob/master/javascript-style-guide.md
其他资源
相关阅读:
http://segmentfault.com/a/1190000000490324
http://blog.csdn.net/lfsf802/article/details/40628453
--继续进步,继续添加
--分享知识,铸就大我,等你指导
最后修改时间:2015-09-16