------------------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:推薦第二種,由於其涉及最少數量的操做和重排列。