高性能JavaScript讀書筆記

来源:https://www.cnblogs.com/liuyongjia/archive/2018/03/03/8502576.html
-Advertisement-
Play Games

零、組織結構 根據引言,作者將全書劃分為四個部分: 一、頁面載入js的最佳方式(開發前準備) 二、改善js代碼的編程技巧(開發中) 三、構建與部署(發佈) 四、發佈後性能檢測與問題追蹤(線上問題優化) 這樣的組織結構也符合我們的開發習慣,首先進入第一部分。 一、JavaScript載入 起因:scr ...


零、組織結構

根據引言,作者將全書劃分為四個部分:
一、頁面載入js的最佳方式(開發前準備)
二、改善js代碼的編程技巧(開發中)
三、構建與部署(發佈)
四、發佈後性能檢測與問題追蹤(線上問題優化)
這樣的組織結構也符合我們的開發習慣,首先進入第一部分。

一、JavaScript載入

起因:script腳本的載入會阻塞瀏覽器渲染頁面和處理用戶交互,如果載入的script腳本太多太大,就會長時間阻塞,造成頁面假死。
解決方案:

1.腳本位置

放在底部。
放在底部可以保證頁面主體結構已經基本載入完成展示給用戶,才去載入script腳本。這條準則也有特例,如果是一些公司的埋點腳本,可能要求必須放在head里,以確保能上報頁面載入時長。

2.組織腳本

減少script數量,合併腳本。
不論是使用concat打包工具合併,還是cdn提供的combo,都能達到該目的。

3.無阻塞腳本

在頁面載入完成之後再去觸發載入js,這樣可以防止script載入阻塞頁面。

原生defer

script標簽自帶defer屬性,可以達到這個目的。捎帶一提,async屬性可以觸發非同步載入,合理利用了寬頻。

動態腳本

或者使用動態腳本元素,通過js文件動態創建script標簽,文件載入完成之後會立刻執行。

這個技術的重點在於不論在何時啟動下載,文件的下載和執行過程都不會阻塞頁面其他進程。

XMLHttpRequest腳本註入

通過XHR載入腳本,由於不是在script標簽中載入,所以可以控制script標簽中的代碼執行時間。在需要的時候再去把script標簽添加到頁面上。
這也是jsonp的原理。

作者推薦的無阻塞模式

先載入很少量的jsLoader代碼,之後通過loader來載入剩餘的代碼。

function loadScript(url, callback) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    
    if (script.readyState) { // IE
        script.onreadystatechange = function () {
            if (script.readyState == 'loaded' || script.readyState == 'complete') {
                script.onreadystatechange = null;
                callback();
            }
        }
    } else { // 其他瀏覽器
        script.onload = function () {
            callback();
        }
    }
    
    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
}

loadScript('rest.js', function () {
    Rest.init()
});

YUI3、LazyLoad、LABjs

作者介紹了上述3個類庫中lazyload的使用方式,其實原理就是上述所說,在體驗上各有不同。關鍵就是loader中監聽script的onload事件,決定script的執行時機。

二、高性能編程技巧

這個部分從2到8章分別介紹不同的提高性能的技巧。

1.數據存取

  • 數據的存取有四種方式,字面量、變數、數據項、對象。字面量和變數快於數組項和對象。
  • 局部變數位於作用域鏈的開始,查找速度最快,所處的位置越深,查找越慢,全局變數查找最慢。
  • with可以影響作用域鏈,try-catch語句中的catch也會影響。慎重使用。
  • 如果當前對象沒有某個屬性或者方法,就會去遍歷原型鏈上的屬性和方法,也會造成性能損耗。
  • 嵌套對象層數越多,也會減慢速度。例如,location.href要快於window.location.href。

  • 解決方法:
    大部分的性能損耗都是與對象查找相關,所以建議緩存對象,減少查找次數。

    2.DOM編程

  • 由於DOM渲染引擎和JS引擎一般是分離實現的,要讓兩個相互獨立的模塊建立通訊,就會產生消耗。所以,我們需要減少DOM操作,已經獲取的DOM節點,緩存下來,防止多次重覆操作。
  • 其次,要註意重繪和重排,對DOM的哪些操作會引起重繪和重排,減少這方面的操作。
    最後,需要註意DOM事件處理用戶交互。

  • 使用innerHTML和原生的document.createElement()類似的方法,速度相差不大。在最新版的webkit內核瀏覽器(chrome和safari)以外,innerHTML會更快,而且相較而言,代碼量也少很多。

  • HTML集合是包含了DOM節點引用的類數組對象,例如document.getElementByName()這樣的方法,需要註意的是HTML集合一直與文檔保持著連接,每次需要新信息的時候,都會重新查詢。

  • 在查找DOM元素時,儘可能使用原生方法,如最新支持比較完善的querySelectorAll()。

  • 在頁面佈局和幾何屬性改變時就需要“重排”,例如:
  1. 添加或者刪除可見的DOM元素
  2. 元素位置改變
  3. 元素尺寸改變(包括:外邊距、內邊距、邊框厚度、寬度、高度等屬性改變)。
  4. 內容改變,例如:文本改變或者圖片被另一個尺寸的圖片替代
  5. 頁面渲染器初始化
  6. 瀏覽器視窗尺寸改變
  • 為了減少重排和重繪,批量修改樣式時,“離線”操作DOM樹,使用緩存,並減少訪問佈局信息的次數。在動畫中使用絕對定位,使用拖放代理。

  • 使用事件委托來減少事件處理器的數量。

3.演算法和流程式控制制

  • 減少迭代的工作量,比如使用局部變數緩存數組的長度,減少查詢次數。
  • 減少迭代次數,使用Duff's Device。
  • 儘可能不用forin,forin要比for、while、do-while要慢。
  • switch比if-else要快,但要綜合考慮代碼可讀性。
  • 判斷條件較多時,查找表要比if-else和switch更快。
  • 遞歸容易造成棧溢出,控制遞歸的迴圈次數。

4.字元串和正則表達式

  • 連接巨大的字元串時,數組項合併在IE7或更早之前版本是最優方法。
  • 如果在現代瀏覽器中,推薦使用簡單的+和+=操作符代替,避免不必要的中間字元串。
  • 回溯是正則的基本組成,也會帶來性能問題。
  • 回溯失控發生在正則表達式本應快速匹配的地方,因為某些特殊的字元串匹配動作導致運行緩慢甚至瀏覽器崩潰。為了避免這種情況,應該使相鄰的字元互斥,避免嵌套量詞對同一字元串的相同部分多次匹配,通過利用預查的原子組去除不必要的回溯。

5.快速響應的用戶界面

  • 任何JavaScript任務不應該超過100ms,否則用戶體驗會變差。
  • JavaScript運行期間,瀏覽器響應用戶交互的行為存在差異。
  • 定時器可用來安排代碼延遲執行,但不一定絕對精確。
  • web worker允許程式員在UI線程外執行JavaScript代碼,從而避免鎖定UI。

6.AJAX

  • 減少請求數
  • 縮短頁面載入時間,頁面主要內容載入完成之後,用Ajax獲取次要內容
  • 代碼錯誤儘可能對用戶屏蔽

7.最佳實踐

  • 避免使用eval和Function構造器帶來雙重求值帶來的性能損耗。
  • 使用直接量創建對象和數組,直接量更快
  • 避免重覆工作,需要檢測瀏覽器時,可使用延遲載入或者條件預載入。
  • 進行數學計算時,考慮使用位運算。
  • 儘量使用原生方法

三、構建與部署

  • 合併JavaScript文件以減少HTTP請求數
  • 使用YUI Compressor壓縮JavaScript文件(事實上,如今nodejs下的打包工具更加好用)
  • 在服務端壓縮JavaScript文件(Gzip編碼)
  • 通過正確設置HTTP響應頭來緩存JavaScript文件,通過向文件名加時間戳來避免緩存問題
  • 使用CDN

四、發佈後性能檢測與問題追蹤

  • 使用網路分析工具找出載入腳本和頁面中其他資源的瓶頸。
  • 把腳本延遲載入可以加快頁面渲染速度,帶來更好的用戶體驗
  • 使用性能分析工具找出腳本運行速度慢的地方,檢查每個函數消耗的時間,以及函數被調用的次數,通過調用棧自身的一些線索來找出需要集中精力優化的地方
    一些工具:
  • YUI Profile
  • Firebug
  • Page Speed
  • Fiddler
  • YSlow
  • dynaTrace Ajax Edition

事實上,這些工具的功能在新版的chrome開發工具都有了,所以我建議好好學習chrome開發者工具。
感謝閱讀。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 接上篇《Android進階之光》--Android新特性 No1: 組件: 1)底部工作條-Bottom Sheets 2)卡片-Cards 3)提示框-Dialogs 4)菜單-Menus 5)選擇器 6)滑塊控制項-Sliders 7)進度和動態 8)Snackbar(底部可操作彈出框)與Toas ...
  • Android 5.0新特性 1)全新的Material Design設計風格 2)支持多種設備 3)全新的通知中心設計--按照優先順序顯示 4)支持64位ART虛擬機 5)多任務視窗Overview 6)設備識別解鎖--比如附近信任設備 7)Ok Google語音指令 8)Face unlock面部 ...
  • 阿裡推薦原因:使用線程池可以減少創建和銷毀線程上所花的時間以及系統資源的開銷,然後之所以不用Executors自定義線程池,用ThreadPoolExecutor是為了規範線程池的使用,還有讓其他人更好懂線程池的運行規則。先說一下關於線程的概念任務:線程需要執行的代碼,也就是Runnable任務隊列 ...
  • 1. 什麼是面向對象? 以下一段話是我在百度上找的解釋: 面向對象(Object Oriented,OO)是軟體開發方法。面向對象的概念和應用已超越了程式設計和軟體開發,擴展到如資料庫系統、互動式界面、應用結構、應用平臺、分散式系統、網路管理結構、CAD技術、人工智慧等領域。面向對象是一種對現實世界 ...
  • UI線程很忙,忙著繪製界面,忙著響應用戶操作,忙著執行App程式員書寫的**多數**代碼 ...
  • 創建對象 第一種:基於Object對象 第二種:對象字面量方式(比較清楚的查找對象包含的屬性及方法) 使用Object構造函數或對象字面量都可以創建對象,但缺點是創建多個對象時,會產生大量的重覆代碼,因此下麵介紹可解決這個問題的創建對象的方法 1、工廠模式 缺點:創建對象交給一個工廠方法來實現,可以 ...
  • 今天終於開始寫代碼了。 希望明天也能恢復更新吧,寒假在家裡實在太過放鬆了,關於寒假,明天拿出時間來好好總結一下,到底幹了些什麼。 用readyState輸出狀態碼是0,未初始化?什麼意思,不太懂…… 問題暫時先留著這裡,應該是很簡單的問題,11點要斷電,不多想了。 大家晚安。 ...
  • 整理自互聯網 整理做隨筆 如有相似純屬抄襲 淺拷貝和深拷貝都是對於JS中的引用類型而言的,淺拷貝就只是複製對象的引用(堆和棧的關係,簡單類型Undefined,Null,Boolean,Number和String是存入堆,直接引用,object array 則是存入桟中,只用一個指針來引用值),如果 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...