------------------2016-7-20更------------------css
最近在看《高性能JavaScript》一书,里面当中,有讲不少提升js性能的书,正在看的过程当中,记下作法以及缘由,供之后学习参考:数组
一、将常用的对象成员、数组项、和域外变量存入局部变量浏览器
缘由:数据存储位置对大地代码总体性能会产生重要的影响,直接变量和局部变量的访问速度快于数组和对象成员。由于局部变量位于做用域链的第一个对象中,全局变量位于做用域链的最后一环。变量在做用域链的位置越深,访问的时间就越长。缓存
1 var doc = document; 2 var db = doc.body; 3 var odiv = doc.getElementById('div1'); 性能优化
二、避免使用with表达式,由于他改变了运行期上下文的做用域链。app
三、同理with,也要注意使用try-catch,由于catch也会改变运行期上下文的做用域链。ide
四、嵌套成员变量会形成重大的性能影响,尽可能少用。函数
五、DOM操做量化问题:布局
//在循坏中更新页面,问题所在:每次循环都对DOM元素访问了两次,一次是读取document.getElementById('here').innerHTML的内容,一次是修改它。 function changeDOM(){ for(var i=0; i < 15000; i++){ document.getElementById('here').innerHTML += 'a'; } } //改变方法,使用局部变量存好改变量,在循环结束时一并修改 function changeDOM(){ var content =''; for(var i=0; i < 15000; i++){ content += 'a'; } document.getElementById('here').innerHTML += content; } //关于js字符串拼接的性能优化问题,js的处理机制是:新建一个临时字符串,将新字符串赋值为 content + 'a' ,而后返回这个新字符串并同时销毁原始字符串。致使字符串的链接效率较低的重要缘由不只在于对于新的临时变量的不断建立,还有js的垃圾回收机制下不断在对象建立期间回收,致使的效率低下。提升效率的办法是用数组的join函数: function changeDOM(){ var content =[]; for(var i=0; i < 15000; i++){ content.push('a'); } document.getElementById('here').innerHTML += content.join(''); } //可是同时也要注意,后来的大部分浏览器都对“+”的链接字符串作了优化,因为SpiderMonkey等引擎对字符串的“+”运算作了优化,结果使用Array.join的效率反而不如直接用“+”!,所以建议是:在IE7如下,使用join,在新浏览器下,除了变量缓存外,不须要作别的优化
六、克隆已有的DOM元素,即element.cloneNode(),比起新建节点来讲,即element.createElement(),会快一点,可是性能提升不是很大。性能
七、遍历数组明显快于一样大小和内容的HTML集合
八、 for循环时,HTML某元素集合的长度不建议直接做为循环终止条件,最好将集合的长度赋给一个变量,而后使用变量做为循环终止条件;
缘由:当每次迭代过程访问集合的length时,它致使集合器更新,在全部的浏览器上都会产生明显的性能损失。
九、须要考虑实际状况的优化,根据7,能够将集合中的元素经过for循坏赋值到数组中,访问数组的数组快于集合。可是要注意对于复制的开销是否值得。
1 function toArray(collection){ 2 var arr = []; 3 var clen = collection.length; 4 for(var i= 0; i < clen; i++){ 5 arr[i] = collection[i]; 6 } 7 8 }
十、获取DOM节点,使用nextSibling方式与childNodes方式,在不一样的浏览器中,这两种方法的时间基本相等。可是在IE中,nextSibling比childNodes好,IE6下,nextSibling比对手快16倍,在IE7下,快105倍。所以,在老的IE中性能严苛的使用条件下,用nextSibling较好。
十一、querySelectorAll()能够联合查询,即querySelectorAll(‘div .warning,div .notice’),在各大浏览器中支持也挺好的,还能够过滤不少非元素节点;
ps:这个网站是:http://caniuse.com/,能够检查HTML、CSS元素在各大浏览器的兼容状况,一个颇有用的网站!
-------------2016-7-21更---------------
十二、重绘和重排版;
重绘:不须要改变元素的长度和宽度,不影响DOM的几何属性;
重排版:影响了几何属性,须要从新计算元素的几何属性,并且其余元素的几何属性有可能也会受影响。浏览器会在重排版过程当中,从新绘制屏幕上受影响的部分。
获取布局信息的操做将致使刷新队列的动做,如使用:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、clientTop、clientLeft、clientHeight、geteComputedStyle()(在IE中此函数成为currentStyle);浏览器此时不得不进行渲染队列中带改变的项目,并从新排版以返回正确值。
解决办法:
a、经过延迟访问布局信息避免重排版。
b、总体修改cssText的css代码,而不是分开访问,修改cssText的属性
1 //访问了4次DOM,第二次开始重排列并强迫渲染队列执行 2 var el = document.getElementById('div1'); 3 el.style.borderLeft = '1px'; 4 el.style.borderRight = '2px'; 5 el.style.padding = '5px'; 6 //改进:改变合并,经过cssText实现 7 var el = document.getElementById('div1'); 8 el.cssText += 'border-left = 1px;border-right = 2px;padding = 5px;';
c、改变css类名来实现样式改变
d、当对DOM元素进行屡次修改时,能够经过如下的步骤减小重绘和重排版的次数:
(注意:此过程引起两次重排版,第一次引起一次,第三次引起一次。若是没有此步骤的话,每次对第二步的改变都有可能带来重排版。)
1 var doc = document; 2 //建立文档子树 3 var frag = doc.createDocumentFragment(); 4 //自定义函数,将修改内容data赋给文档片断frag,具体过程忽略 5 appendDataToElement(frag,data); 6 //注意:添加时实际添加的是文档片断的子节点群,而不是frag本身,只会引起一次重排版 7 doc.getElementById('div1').appendChild(frag);
// 建立一个节点的副本,在副本上进行修改,再让复制节点覆盖原先节点 var oldNode = document.getElementById('old'); var clone = old.cloneNode(); appendDataToElement(clone,data); oldNode.replaceChild(clone,oldNode);
ps:推荐第二种,由于其涉及最少数量的操做和重排列。