高性能javascript筆記

    ----------------------------------------------------------- 第一章 加載和執行 -------------------------------------
1.腳本位置
    瀏覽器在遇到<script>標籤時會等待腳本下載完並執行完纔會繼續渲染頁面
        由於js代碼有可能會改變dom結構,因此須要等待js的執行完成
        遇到<script>標籤 -> 下載腳本 -> 執行腳本 -> 繼續渲染
        舊瀏覽器:逐個下載,逐個執行
        新瀏覽器:併發下載,順序逐個執行
    so: 腳本儘可能放在靠近</body>的底部
        儘量合併腳本(下載一個比下載多個快)
2.延遲的腳本
    defer:馬上下載,等到onload事件被觸發前才執行(僅IE4.0+和Firefox3.5+支持)
    動態建立<script>節點:添加到頁面時開始下載,下載完成馬上執行
        * 下載完成的事件:readystatechange(IE)、onload(其餘瀏覽器)
    XHR腳本注入:XMLHttpRequest來獲取js文件內容,再動態建立<script>節點
        * 必須處於相同域,不適用大型Web應用
3.推薦的方式
    先添加動態加載所需的代碼,而後加載其餘代碼:
        <script type="text/javascript" src = "loader.js"></script>
        <script type="text/javascript">
            loadScript("the-rest.js"),function(){
                Application.init();
            }
        </script>
        放置</body>閉合標籤前,保證DOM結構已經建立完畢,無需其餘的時間,例如window.onload來檢測頁面是否準備好
4.類庫
    LazyLoad.js:
        <script type="text/javascript" src = "lazyload-min.js"></script>
        <script type="text/javascript">
            LazyLoad.js(["first.js","second.js"]),function(){
                Application.init();
            }
        </script>
    lab.js:
        <script type="text/javascript" src = "lab.js"></script>
        <script type="text/javascript">
            $LAB.script("first.js").wait()    // 若是須要按序執行則須要加上wait()
                .script("second.js")
                .wait(function(){
                        Application.init();
                });
        </script>
   
--------------------------------第二章 數據訪問---------------------------------------
1.做用域鏈和標識符解析
    內部屬性[[Scope]] --- 做用域鏈  --- 0 --- 活動對象([[Scope]]屬性中所包含的對象,即函數範圍內的變量)
                                    --- 1 --- 全局對象(this, window, document 等等全局變量)
2.so 儘可能把鏈深處的變量存儲到局部變量裏,介以提高性能
    * 採用優化過的js引擎不存在這種問題,老版的IE、Firefox和Safari都有問題javascript

3.改變做用域鏈:
        with(document){...}    //with把document推動了做用域鏈的第一層,可是致使訪問局部變量路徑變遠了,因此不推薦
        try{}catch(ex){}    //catch裏面把異常對象推入了做用域鏈的頭部html

4.訪問對象也同樣,首先在實例中查找,而後再去原型鏈中查找
    so 若是須要訪問屢次,那麼緩存對象屬性能夠提高性能
   
--------------------------------第三章 DOM編程---------------------------------------
1.儘可能少訪問DOM,把運算留在ECMAScript這一端處理java

2.innerHTML屬性和相似document.createElement()、document.createTextNode()的原生DOM方法性能差很少正則表達式

3.cloneNode()比createElement要稍快一點算法

4.HTML集合
    document.getElementsByName();
    document.getElementsByClassName();
    document.getElementsByTagName();
    HTML集合是動態的,類數組,提供一個length屬性
    * 訪問length屬性時會從新執行一次查詢的過程
    so,緩存length屬性頗有必要
   
5.只返回元素節點
    children                    childNodes
    childElementCount            childNodes.length
    firstElementChild            firstChild
    lastElementChild            lastChild
    nextElementSibling            nextSibling
    previousElementSibling        previousSibling
   
6.選擇器API
    原生DOM方法:querySelectorAll();
   
7.重繪與重排
    構建DOM樹與渲染樹 --- 繪製頁面元素
    重排:
        添加、刪除DOM元素
        元素位置改變
        元素尺寸改變
        內容改變(例如文本改變、圖片被另一個不一樣尺寸的圖片替代)
        頁面渲染器初始化
        瀏覽器窗口尺寸改變
    瀏覽器經過隊列化修改並批量執行來優化重排過程,但如下屬性會強制刷新隊列:
    offsetTop, offsetLeft, offsetWidth, offsetHeight
    scroll...
    client...
    getComputedStyle()(currentStyle in IE)
    以上屬性須要返回最新的佈局信息,因此瀏覽器須要執行隊列中的"待處理變化"並觸發重排以返回正確的值
    so 以上屬性儘可能少使用,而且使用這些屬性的位置應該在修改佈局信息的後面,中間的話會致使屢次重排編程

8.最小化重繪和重排
    ·合併屢次全部的改變一次處理
    ·批量修改DOM
        脫離文檔流
        應用多重改變
        帶回文檔
    三種方式:隱藏元素 --- 修改 --- 從新顯示
                使用文檔片斷(document fragment)
                拷貝 --- 修改拷貝 --- 替換原始(replaceChild(new, old))
   
9.緩存佈局信息windows

10.讓元素脫離動畫流
    絕對定位頁面上的動畫元素,將其脫離文檔流
    讓元素動起來,只重繪了該元素,會臨時覆蓋部分頁面
    動畫結束時恢復定位,只下移一次文檔的其餘元素跨域

11.元素不少時應避免使用:hover這個CSS僞選擇器數組

12.事件委託
    只綁定最外圍的元素點擊事件,判斷來源是不是目標瀏覽器

--------------------------------第四章 算法和流程控制---------------------------------------
1.for-in循環的性能只有其餘循環的1/7,
    so 儘可能不要使用for-in來遍歷對象的屬性名

2.少許條件用if-else, 大量條件用switch-case

3.列表查找比循環查找要快
    so, 數據放置一個Array中, 經過位置來查找
   
4.儘可能減小循環

5.存在重複的計算結果時,可使用緩存

--------------------------------第五章 字符串和正則表達式---------------------------------------
1.字符串鏈接
    把基礎字符串及放置左邊能夠提高性能
    * 由於除IE外,其餘瀏覽器會嘗試爲左側的字符串分配更多的內存,而後簡單地將第二個字符串拷貝至它的末尾
   
2.Array.prototype.join();
    String.prototype.concat();    //concat比普通的+和+=以及join慢一點

3.正則表達式的編譯很快,只須要注意別在循環中重複編譯正則表達式就行
    while(/regex1/.test(str1))
   
4.只是檢測位置不適用正則表達式
    例如檢測是否以;結尾:
        /;$/ --- str.charAt(str.length-1)== ";";
    其餘函數有slice、substr、substring、indexOf和lastIndexOf
   
5.去除首尾空格
    用兩個子表達式綜合效率要高一些,尤爲是在處理長字符串時
    str.replace(/^\s+/,"").replace(/\s+$/,"");
    * 其餘有一次性處理完的,但多少有各方面的性能問題
        比方說/^\s+|\s+$/,每一個字符串都會去匹配這兩個分支條件

--------------------------------第六章 快速響應的用戶界面---------------------------------------
1.js的執行不該超過100毫秒(用戶體驗中能忍受的頁面阻塞時間最大值)

2.定時器的推薦最小值爲25毫秒
    * windows系統的最小識別爲15毫秒,設置一個小於15毫秒的定時值,IE會鎖定
    * 在小於10毫秒時,各瀏覽器各系統均會有不一樣的表現
   
3.能夠經過定時器來依次執行多個任務
    * 將一個任務分割成多個任務,用定時器來執行
   
4.Web Workers
    Worker沒有綁定UI線程,適用於純數據處理,與網頁代碼經過事件接口進行通訊
    網頁代碼:
        var worker = new Worker("code.js");
        worker.onmessage = faunction(event){
            // ...
        }
        worker.postMessage("Thyiad");
    worker代碼(code.js):
        importScripts("file1.js", "file2.js");
        self.onmessage = function(event){
            self.postMessage("Hello, " + event.data + "!");
        }
       
--------------------------------第七章 AJAX---------------------------------------
1.經常使用的三種技術是:XHR、動態腳本注入和multipart XHR

2.XHR
    readyState的值
        3    正在與服務器交互
        4    整個響應已接收完畢,可進行操做
    * GET經常使用來請求數據,POST則用來發送數據
        一個GET請求只會發送一次數據包,而一個POST請求會發送兩次數據包(一個裝載頭一個裝載正文)
        應該在參數接近或超過2048個字符時,才應該使用POST獲取數據,由於IE限制URL長度
    * 不能跨域請求數據

3.動態腳本注入
    動態建立一個script元素,設置src屬性爲不一樣域的URL
    * 返回的響應消息必須是可執行的JavaScript代碼
   
4.Multipart XHR
    一次請求多個資源,從readyState值爲3時開始設定一個定時器監聽處理數據(須要本身定義數據格式並處理)
    * 這種方式資源不會被緩存
    * IE六、7不支持readyState爲3的狀態和data:URL

5.Beancons - 信標
    經過建立一個Image,設定src來回傳數據
        var beacon = new Image();
        beacon.src=url+'?'+params.join('&');
        beancon.onload = function(){    // 經過監聽image的load事件來處理簡單返回時間
            if(this.width === 1){        // 若是不須要返回數據,那麼響應中應該發送一個 204 No Content 狀態碼(即:不帶消息正文)
            }                            // 以阻止客戶端繼續等待永遠不會到來的消息正文
            else{}
        }
       
6.數據格式
    XML        不推薦,數據量大解析又慢
    JSON    推薦,數據輕便解析又快
    JSON-P    返回的文本做爲js代碼直接執行(用eval直接調用)
    HTML    不推薦,既緩慢又臃腫
    自定義    同JSON,適用的情景下速度還會比JSON更快點
   
7.緩存數據
    用GET請求數據、響應中發送 Expires 頭信息:Expires: Mon, 28 Jul 2015 23:30:00 GMT    // 告訴瀏覽器緩存此響應到7月
    本地數據存儲:使用對象的屬性存儲緩存(鍵存url,值存返回數據)
    * 本地存儲最適用移動設備,大多移動設備的瀏覽器都很小或沒有緩存
   
--------------------------------第八章 編程實踐---------------------------------------
1.避免雙重求值
    儘可能不使用eval和Function構造函數,以免雙重求值帶來的性能消耗
    一樣的,應該給setTimeout()和setInterval()傳入函數而不是字符串做爲參數
   
2.使用直接量建立對象和數組 - 效率更高

3.不要重複工做
    當須要檢測瀏覽器時,可以使用延遲加載或條件預加載
    延遲加載:
        function addHandler(target, eventType, handler){
            if(target.addEventListener){
                addHandler = function(target, eventType, handler){
                    target.addEventListener(eventType, handler, false);
                }
            }
            else{
                addHandler = function(target, eventType, handler){
                    target.attachEvent("on"+eventType, handler);
                }
            }
           
            addHandler(target, eventType, handler);
        }
    條件預加載:
        var addHandler = document.body.addEventListener ?
            function(target, eventType, handler){
                    target.addEventListener(eventType, handler, false);
                } :
            function(target, eventType, handler){
                    target.attachEvent("on"+eventType, handler);
                };

4.使用速度快的部分
    位操做
        toString()方法把數字轉換爲二進制形式的字符串:
            var num = 25;
            alert(num.toString(2));        //"11001"
        是否爲2的整數:
            var num = 25;
            if(num & 1){    // 奇數&1 => 1
            }
            else{}            // 偶數
        位掩碼:
            var OPTION_A = 1, OPTION_B = 2, OPTION_C = 4, OPTION_D = 8, OPTION_E = 16;
            var options = OPTION_A | OPTION_C | OPTION_D;
            if(options & OPTION_A){    //選項A是否在列表中
                // ...
            }
           
5.原生方法
    儘可能使用原生方法,好比數學計算(Math)和CSS選擇器(querySelector()、querySelectorAll())
   
--------------------------------第九章 構建並部署高性能JavaScript應用---------------------------------------
1.Apache Ant

2.合併多個JavaScript文件

3.預處理JavaScript文件
    在js代碼中添加宏定義(#define, #undef)和條件編譯(#if, #ifdef, #ifndef)

4.JavaScript壓縮
    JSMin                http://www.crockford.com/javascript/jsmin.html
    YUI Compressor        http://developer.yahoo.com/yui/compressor
    Closure Compiler    http://code.google.com/closure/compiler/
    Packer                http://dean.edwards.name/packer/

5.JavaScript的HTTP壓縮
    Accept-Encoding HTTP頭:值爲gzip、compress、deflate和identity
        服務器會選擇最合適的編碼方法,經過Content-Encoding HTTP頭來告知瀏覽器
       
6.緩存JavaScript文件
    * Expires HTTP 響應頭
    * 客戶端存儲機制(js本身控制)
    * HTML5 離線應用緩存(manifest屬性,mime type爲text/cache-manifest)
   
7.處理緩存問題
    推薦使用時間戳後綴
   
8.CDN
   
--------------------------------第十章 工具---------------------------------------
1.原生分析
    new Date();    //經過Date相減
   
2.YUI Profiler
   
3.FireBug

4.Console API    profile()、profileEnd()        console.profile("regexTest");        regexTest();        console.profileEnd();        * profileEnd()會阻塞後續執行,因此能夠將profileEnd()調用封裝在setTimeout中        5.Page Speed    對如何重構進行分析建議,好比哪些腳本在load以前沒有用到過,能夠延遲加載    * FireBug插件    6.Fiddler    HTTP調試代理工具,整個網絡過程的Timeline進行分析,哪塊佔用時間多須要優化    7.YSlow    分析後的優化建議工具      * FireBug插件        8.dynatrace Ajax Edition    同Fiddler的做用,能夠監控整個過程的時間,更能深刻到特定的事件

相關文章
相關標籤/搜索