《高性能網站建設進階指南》:
1.使用局部變量,避免深入作用域查找,局部變量是讀寫速度最快的;把函數中使用次數超過一次的對象屬性和數組存儲為局部變量是一個好方法;比如for循環中的.length通常可以保存為局部變量。
2,多個if時,if順序按概率降序排列
3,當僅判斷一兩個條件時,if通常比switch更快,當有兩個以上條件且條件比較簡單(不是范圍判定)時,switch通常更快;因為多數情況下,switch語句中執行單個條件的時間比if短;
4,循環中把循環變量遞減到0,而不是遞增到長度,把條件改成了與0比較,速度更快,如for(var i=arr.length;i--){};
5,避免for in;for in是用來遍歷對象的可枚舉屬性,需要遍歷整個原型鏈來查找可枚舉屬性,若
Array.prototype.myf=function(){};//(數據屬性默認都是可枚舉的)
var a=['a','b'];for(var p in a){console.log(p+','+a[p]);}
輸出將是:
0,a
1,b
myf,function (){}
對于object同樣如此,所以一般需要用hasOwnProperty來確保只變例對象實例自身的屬性。
若已知對象的屬性,則采用普通的for循環性能優于for in;如var arr=['p1','p2','p3'];for(){process(obj[arr[i]]);}
6,性能優化:拆分js,減少初次render的下載量,注意會出現用戶點擊時,事件綁定還沒完成的情況。js延遲下載;
7,css選擇符;匹配順序是從右到左的;避免通配符,用classname代替標簽名,利用屬性繼承。。。。。。
?
《高性能javascript》:
?V8 引擎由以下幾個核心部分組成:
- 基本編譯器(base compiler),在你的代碼運行之前,它會分析你的 JavaScript 代碼并生成本地機器碼,而不是執行字節碼或簡單地解釋它。這種機器碼起初是沒有被高度優化的。
- V8 將對象解析為對象模型(object model)。對象是在 JavaScript 中是以關聯數組的方式呈現的,但是在 V8 引擎中,它們是通過隱藏類(hidden classes)的方式來表示的。這是一種可以優化查找的內部類型機制。
- 一個運行時分析器(runtime profiler),它監視正在運行的系統,并標識 “hot” 函數,也就是那些最后會花費大量運行時間的代碼。
- 一個優化編譯器(optimizing compiler),它重新編譯和優化那些被運行時分析器標識為 “hot” 的代碼,并進行 “內聯” 等優化(例如,在函數被調用的地方用函數主體去取代)。
- V8支持逆優化(deoptimization),這意味著,如果優化編譯器發現在某些假定的情況下,把一些已經優化的代碼進行了過度的優化,它會舍棄優化后的代碼。
- 垃圾回收器,理解它的運作原理和理解如何優化你的JavaScript代碼同等重要。
垃圾回收是內存管理的一種機制,垃圾回收器的概念是,它將試圖回收那些不再被使用的對象所占據的內存,在像 JavaScript 這種支持垃圾回收的語言中,如果程序中仍然存在指向一個對象的引用,那么該對象將不會被回收。
在大多數情況下,我們沒有必要去手動得解除對象的引用(de-referencing)。只需要簡單滴將變量放在需要它們的位置(在理想的情況下,盡可能使用局部變量,也就是說,在它們被使用的函數中聲明它們,而不是在更外層的作用域),垃圾就能正確地被回收。
在 JavaScript 中,強制進行垃圾回收是不可能的,而且你也不應該嘗試這樣做,因為垃圾回收是由運行時控制,并且它通常知道垃圾回收的最佳時機。在可能的情況下,盡量避免使用?delete
,
盡管如此,你肯定會發在許多流行的 JavaScript 庫中使用了 delete - 這有它語言目的。這里的主旨是,避免在運行時修改 “hot” 對象的結構,JavaScript 引擎可以檢測到這些 “hot” 的對象,并嘗試對其進行優化。如果在對象的生命期中沒有遇到重大的結構改變,引擎的檢測和優化過程會來得更加容易,而使用?delete
?則會觸發對象結構上的這種改變。
不少人對?null
?的使用上也存在誤解。將一個對象引用設置為?null
,并不是意味著“清空”該對象,只是將它的引用指向?null
。使用?o.x = null
?比使用?delete
?會更好些,但這甚至可能也是不必要的。
如果此引用是當前對象的最后引用,那么該對象就滿足了垃圾回收的資格。如果此引用不是當前對象的最后引用,則該對象是可訪問的,而不會被垃圾回收。
另外需要注意的是,全局變量在頁面的生命周期中是不會被垃圾回收器清理的。只要頁面保持打開狀態,全局對象就會常駐在內存當中。只有當刷新頁面、導航到其他頁面、關閉標簽頁或退出瀏覽器時,全局變量才會被清理。函數作用域的變量超出作用域范圍時,它就會被清理。當函數完全結束,并且再沒有任何引用指向其中的變量,函數中的變量會被清理。
經驗法則:
為了使垃圾回收器盡早回收盡可能多的對象,請不要保留(hold on)不再需要的對象。(qi:比如在函數里return一個不需要的變量,因為這會導致變量不會被回收)這里有幾點需要謹記:
- 就像之前所說的那樣,比手動刪除變量引用更好的方式是,在恰當的作用域中使用變量,例如,盡量在函數作用域中聲明變量,而盡可能不要聲明不會被回收的全局變量,這將意味著更干凈更省心的代碼。
- 確保解綁那些不再需要的事件監聽器,尤其是那些即將被移除的 DOM 對象所綁定的事件。
- 如果你正在使用數據緩存,確保手動清理緩存或者使用衰老機制,避免緩存中儲存大量不會被重用的數據。
數組字面量非常有用,它可以暗示數組的大小和類型。它通常用在體積不大的數組中。
? | // V8 知道你需要一個長度為 4 并且儲存數字的數組: |
qi:閉包也會導致變量不會被回收,事件委托:$('table').on('click',?td,?...)優于$('table?td').on('click', ...)
當瀏覽器重新渲染文檔中的元素時需要重新計算它們的位置和幾何形狀時,我們稱之為回流。回流會阻塞用戶在瀏覽器中的操作,因此理解提升回流時間是非常有幫助的。使用document.createDocumentFragment()創建了一虛擬的節點對象(節點對象包含所有屬性和方法),保存多個小節點后在append;在所有節點類型中,只有文檔片段DocumentFragment在文檔中沒有對應的標記。DOM規定文檔片段(documentfragment)是一種”輕量級“的文檔,可以包含和控制節點,但不會像完整的文檔那樣占用額外資源。即當請求把一個 DocumentFragment 節點插入文檔樹時,插入的不是 DocumentFragment 自身,而是它的所有子孫節點。這使得 DocumentFragment 成了有用的占位符,暫時存放那些一次插入文檔的節點。它還有利于實現文檔的剪切、復制和粘貼操作,尤其是與 Range 接口一起使用時更是如此.
qi: css性能:盡量repaint而不是reflow.
顯式設置圖片的寬高:
當瀏覽器加載頁面的HTML代碼時,有時候需要在圖片下載完成前就對頁面布局進行定位。如果HTML里的圖片沒有指定尺寸(寬和高),或者代碼描述的尺寸與實際圖片的尺寸不符時,瀏覽器則要在圖片下載完成后再“回溯”該圖片并重新顯示,這會消耗額外時間。所以,最好為頁面里的每一張圖片都指定尺寸,不管是在頁面HTML里的<img>標簽,還是在CSS里。
瀏覽器解析頁面順序:參考http://www.alloyteam.com/2015/05/wang-ye-xing-neng-zhi-html-css-javascript/;
qi:瀏覽器得到某個頁面后,按順序開始解析,遇到css file和image,發相應的請求,同時繼續往下,到結束就構建好了無樣式的dom tree,css file下載后解析得到CSSOM,結合dom tree開始渲染得到render tree,至此在chrome developer tool里就是domComplete完成的時間(藍色豎線),等image下載好插入render tree,至此在chrome developer tool里就是domLoader完成的時間(紅色豎線).因為js有可能改變dom tree結構,所以如果遇到js file會暫時停止其他渲染行為,等js解析完成后再渲染。?使用async標識的javascript,瀏覽器將異步執行javascript不會阻塞正常的dom渲染。