本期我來給你們推薦的書是《高性能JavaScript》,在這本書中咱們可以瞭解 javascript 開發過程當中的性能瓶頸,如何提高各方面的性能,包括代碼的加載、運行、DOM交互、頁面生存週期等。一樣咱們今天仍是用思惟導圖的方式來精讀一遍。(思惟導圖圖片可能有點小,記得點開看,你會有所收穫)javascript
管理瀏覽器中的 JavaScript 代碼是個棘手的問題,由於代碼執行阻塞了其餘瀏覽器處理過程,諸如用戶 界面繪製。每次遇到<script>
標籤,頁面必須停下來等待代碼下載(若是是外部的)並執行,而後再繼續處 理頁面其餘部分。可是,有幾種方法能夠減小 JavaScript 對性能的影響:前端
<script>
標籤放置在頁面的底部,緊靠 body 關閉標籤</body>
的上方。此法能夠保證頁面在腳本 運行以前完成解析。<script>
標籤越少,頁面的加載速度就越快,響應也更加迅速。不論外部腳本 文件仍是內聯代碼都是如此。有幾種方法可使用非阻塞方式下載 JavaScript:java
<script>
標籤添加 defer 屬性(只適用於 Internet Explorer 和 Firefox 3.5 以上版本)<script>
元素,用它下載並執行代碼經過使用上述策略,你能夠極大提升那些大量使用 JavaScript 代碼的網頁應用的實際性能。git
在 JavaScript 中,數據存儲位置能夠對代碼總體性能產生重要影響。有四種數據訪問類型:直接量,變 量,數組項,對象成員。它們有不一樣的性能考慮。github
直接量和局部變量訪問速度很是快,數組項和對象成員須要更長時間。局部變量比域外變量快,由於它位於做用域鏈的第一個對象中。變量在做用域鏈中的位置越深,訪問所需 的時間就越長。全局變量老是最慢的,由於它們老是位於做用域鏈的最後一環。避免使用 with 表達式,由於它改變了運行期上下文的做用域鏈。並且應當當心對待 try-catch 表達式的 catch 子句,由於它具備一樣效果。嵌套對象成員會形成重大性能影響,儘可能少用。面試
一個屬性或方法在原形鏈中的位置越深,訪問它的速度就越慢。通常來講,你能夠經過這種方法提升 JavaScript 代碼的性能:將常用的對象成員,數組項,和域外變 量存入局部變量中。而後,訪問局部變量的速度會快於那些原始變量。經過使用這些策略,你能夠極大地提升那些須要大量 JavaScript 代碼的網頁應用的實際性能。正則表達式
DOM 訪問和操做是現代網頁應用中很重要的一部分。但每次你經過橋樑從 ECMAScript 島到達 DOM 島 時,都會被收取「過橋費」。爲減小 DOM 編程中的性能損失,請牢記如下幾點:算法
最小化 DOM 訪問,在 JavaScript 端作儘量多的事情。在反覆訪問的地方使用局部變量存放 DOM 引用.當心地處理 HTML 集合,由於他們表現出「存在性」,老是對底層文檔從新查詢。將集合的 length 屬性緩 存到一個變量中,在迭代中使用這個變量。若是常常操做這個集合,能夠將集合拷貝到數組中。編程
若是可能的話,使用速度更快的 API,諸如 querySelectorAll()和 firstElementChild。注意重繪和重排版;批量修改風格,離線操做 DOM 樹,緩存並減小對佈局信息的訪問。動畫中使用絕對座標,使用拖放代理。使用事件託管技術最小化事件句柄數量。跨域
正如其餘編程語言,代碼的寫法和算法選用影響 JavaScript 的運行時間。與其餘編程語言不一樣的是, JavaScript 可用資源有限,因此優化技術更爲重要。
for,while,do-while 循環的性能特性類似,誰也不比誰更快或更慢。除非你要迭代遍歷一個屬性未知的對象,不然不要使用 for-in 循環。改善循環性能的最好辦法是減小每次迭代中的運算量,並減小循環迭代次數。
通常來講,switch 老是比 if-else 更快,但並不老是最好的解決方法。當判斷條件較多時,查表法比 if-else 或者 switch 更快。
瀏覽器的調用棧尺寸限制了遞歸算法在 JavaScript 中的應用;棧溢出錯誤致使其餘代碼也不能正常執行。若是你遇到一個棧溢出錯誤,將方法修改成一個迭代算法或者使用製表法能夠避免重複工做。
運行的代碼總量越大,使用這些策略所帶來的性能提高就越明顯。
密集的字符串操做和粗淺地編寫正則表達式多是主要性能障礙,但本章中的建議可幫助您避免常見缺陷。當鏈接數量巨大或尺寸巨大的字符串時,數組聯合是 IE7 和它的早期版本上惟一具備合理性能的方法。若是你不關心 IE7 和它的早期版本,數組聯合是鏈接字符串最慢的方法之一。使用簡單的+和+=取而代之, 可避免(產生)沒必要要的中間字符串。
回溯既是正則表達式匹配功能基本的組成部分,又是正則表達式影響效率的常見緣由。回溯失控發生在正則表達式本應很快發現匹配的地方,由於某些特殊的匹配字符串動做,致使運行緩慢 甚至瀏覽器崩潰。避免此問題的技術包括:使相鄰字元互斥,避免嵌套量詞對一個字符串的相同部分屢次 匹配,經過重複利用前瞻操做的原子特性去除沒必要要的回溯。
提升正則表達式效率的各類技術手段,幫助正則表達式更快地找到匹配,以及在非匹配位置上花費更少 時間(見《更多提升正則表達式效率的方法》)。正則表達式並不老是完成工做的最佳工具,尤爲當你只是搜索一個文本字符串時。
雖然有不少方法來修整一個字符串,使用兩個簡單的正則表達式(一個用於去除頭部空格,另外一個用於 去除尾部空格)提供了一個簡潔、跨瀏覽器的方法,適用於不一樣內容和長度的字符串。從字符串末尾開始 循環查找第一個非空格字符,或者在一個混合應用中將此技術與正則表達式結合起來,提供了一個很好的 替代方案,它不多受到字符串總體長度的影響。
JavaScript 和用戶界面更新在同一個進程內運行,同一時刻只有其中一個能夠運行。這意味着當 JavaScript 代碼正在運行時,用戶界面不能響應輸入,反之亦然。有效地管理 UI 線程就是要確保 JavaScript 不能運行 太長時間,以避免影響用戶體驗。最後,請牢記以下幾點:
網頁工人線程是新式瀏覽器才支持的特性,它容許你在 UI 線程以外運行 JavaScript 代碼而避免鎖定 UI。網頁應用程序越複雜,積極主動地管理 UI 線程就越顯得重要。沒有什麼 JavaScript 代碼能夠重要到允 許影響用戶體驗的程度。
高性能 Ajax 包括:知道你項目的具體需求,選擇正確的數據格式和與之相配的傳輸技術。
做爲數據格式,純文本和 HTML 是高度限制的,但它們可節省客戶端的 CPU 週期。XML 被普遍應用 廣泛支持,但它很是冗長且解析緩慢。JSON 是輕量級的,解析迅速(做爲本地代碼而不是字符串),交 互性與 XML 至關。字符分隔的自定義格式很是輕量,在大量數據集解析時速度最快,但須要編寫額外的 程序在服務器端構造格式,並在客戶端解析。
當從頁面域請求數據時,XHR 提供最完善的控制和靈活性,儘管它將全部傳入數據視爲一個字符串, 這有可能下降解析速度。另外一方面,動態腳本標籤插入技術容許跨域請求和本地運行 JavaScript 和 JSON, 雖然它的接口不夠安全,並且不能讀取信息頭或響應報文代碼。多部分 XHR 可減小請求的數量,可在一次響應中處理不一樣的文件類型,儘管它不能緩存收到的響應報文。當發送數據時,圖像燈標是最簡單和最 有效的方法。XHR 也可用 POST 方法發送大量數據。
除這些格式和傳輸技術以外,還有一些準則有助於進一步提升 Ajax 的速度:
Ajax 是提高你網站潛在性能之最大的改進區域之一,由於不少網站大量使用異步請求,又由於它提供 了許多不相關問題的解決方案,這些問題諸如,須要加載太多資源。對 XHR 的創造性應用是如此的與衆 不一樣,它不是呆滯不友好的界面,而是響應迅速且高效的代名詞;它不會引發用戶的憎恨,誰見了它都會 愛上它。
JavaScript 提出了一些獨特的性能挑戰,關係到你組織代碼的方法。網頁應用變得愈來愈高級,包含的 JavaScript 代碼愈來愈多,出現了一些模式和反模式。請牢記如下編程經驗:
開發和部署過程對基於 JavaScript 的應用程序能夠產生巨大影響,最重要的幾個步驟以下:
全部這些步驟應當自動完成,不管是使用公開的開發工具諸如 Apache Ant,仍是使用自定義的開發工具 以實現特定需求。若是你使這些開發工具爲你服務,你能夠極大改善那些大量使用 JavaScript 代碼的網頁 應用或網站的性能。
當網頁或應用程序變慢時,分析網上傳來的資源,分析腳本的運行性能,使你可以集中精力在那些須要 努力優化的地方。使用網絡分析器找出加載腳本和其它頁面資源的瓶頸所在,這有助於決定哪些腳本須要延遲加載,或者 進行進一步分析。傳統的智慧告訴咱們應儘可能減小 HTTP 請求的數量,儘可能延遲加載腳本以使頁面渲染速度更快,向用戶 提供更好的總體體驗。使用性能分析器找出腳本運行時速度慢的部分,檢查每一個函數所花費的時間,以及函數被調用的次數, 經過調用棧自身提供的一些線索來找出哪些地方應當努力優化。雖然花費時間和調用次數一般是數據中最有價值的點,仍是應當仔細察看函數的調用過程,可能發現其 它優化方法。這些工具在那些現代代碼所要運行的編程環境中再也不神祕。在開始優化工做以前使用它們,確保開發時 間用在解決問題的刀刃上。
爲了系統的串聯前端知識,我平時喜歡用思惟導圖來記錄讀書筆記,我在 github 建了倉庫放這些思惟導圖的原件,和讀書筆記。若是你也喜歡用思惟導圖的方式來記錄讀書筆記,也歡迎和我一同維護這個倉庫,歡迎留言或則微信(646321933)與我交流