高性能的JavaScript -- 讀書筆記

高性能的JavaScriptjavascript

1、      加載和運行java

  1. 將腳本放在底部

腳本下載解析執行時,頁面已經加載完成並顯示在用戶面前正則表達式

  1. 成組腳本

減小外部腳本文件數量,整合成一個文件算法

  1. 延遲腳本
  2. 動態腳本元素

非阻塞方式編程

  1. XMLHttpRequest

var xhr = new XMLHttpRequest();數組

xhr.open(「get」, 「file.js", true);瀏覽器

xhr.onreadystatechange = function() {緩存

    if(xhr.readyState == 4) {閉包

        if ….app

          var script = document.createElement(「script」);

          script.type = 「text/javascript」;

          script.text = xhr.responseText;

          document.body.appendChild(script);

    }

}

優勢:可下載不當即執行的JavaScript代碼

限制:JavaScript文件必須與頁面放置在同一個域內

  1. 推薦的非阻塞模式

2、      數據訪問

  1. 四種基本的數據訪問方式:

直接量、變量、數組項、對象成員

  1. 管理做用域

每一個JavaScript函數中都有一個僅供JavaScript引擎使用的內部屬性爲[[Scope]]。該屬性包含了函數被建立的做用域鏈中對象的集合。

 

運行期上下文的做用域鏈中,一個標識符位置越深,它的讀寫速度就越慢。因此,函數中局部變量的訪問速度老是最快的,而全局變量一般是最慢的。

  1. 改變做用域鏈

with表達式:做用域鏈前段插入了一個新的對象,局部變量的訪問速度變慢。最好不要用。

try-catch表達式:catch子句執行完畢,做用域鏈返回原來的狀態。

  1. 閉包,做用域,和內存

當閉包被運行時,一個運行期上下文將被建立,它的做用域鏈與[[Scope]]中引用的兩個相同的做用域同時被初始化,而後一個新的激活對象爲閉包自身被建立。

腳本中最好當心地使用閉包。

  1. 對象成員

對象成員比直接量和局部變量訪問速度慢,在某些瀏覽器上比訪問數組項還要慢。

因此可能的話避免使用它們,只在必要狀況下使用對象成員。

  1. 總結:

提升性能:將常用的對象成員,數組項,和域外變量存入局部變量中。而後,訪問局部變量的速度會快於那些原始變量。

3、      DOM編程

DOM操做代價昂貴

三類問題:

l  訪問和修改DOM元素

l  修改DOM元素的樣式,形成重繪和從新排版

l  經過DOM事件處理用戶響應

  1. DOM訪問和修改

輕輕地觸摸DOM,並儘可能保持在ECMAScript範圍內。

不標準卻被良好支持innerHTML和純DOM方法如document.createElement()的性能差異不大。舊的瀏覽器上innerHTML快,新瀏覽器上DOM方法更快。

  1. 節點克隆

克隆節點更有效率,但提升不太多。

  1. HTML 集合對象

遍歷數組比遍歷集合快。

每次迭代過程訪問集合length屬性,性能低。應將length屬性緩存到一個變量中,而後在循環判斷條件中使用這個變量。

  1. 若是瀏覽器支持document.querySelectAll(),最好使用它
  2. 重繪和重排版

瀏覽器下載完全部頁面HTML標記,JavaScript,CSS,圖片後,它解析文件並建立兩個內部數據

l  一棵DOM樹:表示頁面結構

l  一棵渲染樹:表示DOM節點如何顯示

 

當佈局和幾何改變時須要重排版:

l  添加或刪除可見的DOM元素

l  元素位置改變

l  元素尺寸改變

l  內容改變

l  最初的頁面渲染

l  瀏覽器窗口改變尺寸

 

  1. 最小化重繪和重排版

由於代價昂貴,因此好的策略是減小此類操做發生機會。將多個DOM和風格改變合併到一個批次中一次性執行。

l  隱藏元素,進行修改,而後再顯示它。

display = none; 修改;display = block;

l  在已存DOM以外建立一個子樹,而後拷貝到文檔。

createDocumentFragment();append();

l  拷貝原始元素,修改副本,覆蓋原始元素。

cloneNode();replaceChild();

第二種文檔片斷最優

 

  1. 緩衝佈局信息
  2. 將元素提出動畫流

使用如下步驟能夠避免對大部分頁面進行重排版

l  絕對座標定位頁面動畫元素,使它位於頁面佈局流以外

尺寸改變時只會覆蓋其餘元素

l  啓動元素動畫

l  當動畫結束時,從新定位,只一次下移文檔其餘元素位置

  1. 事件託管

事件逐層冒泡總被父元素捕獲;

只需在一個包裝元素上掛接一個句柄,用於處理子元素髮生的全部事件;

 

DOM標準,每一個事件有三個階段:

捕獲,到達目標,冒泡

10. 總結

爲減小DOM編程中的性能損失,注意如下幾點:

l  最小化DOM訪問,在JavaScript端作儘量多的事情

l  在反覆訪問的地方使用局部變量存放DOM引用

l  當心處理HTML集合,將length屬性緩存到一個變量中

l  使用速度更快的API,如querySelectorAll()和firstElementChild

l  注意重繪和重排版;批量修改風格,離線操做DOM樹,緩存並減小對佈局信息的訪問

l  動畫中使用絕對座標,使用拖放代理

l  使用時間託管技術最小化事件句柄數量

 

4、      算法和流程控制

代碼總體結構是執行速度的決定因素之一

  1. 循環

for-in循環比其餘普通循環明顯要慢;

由於每次迭代操做要搜索實例或原形的屬性。

減小迭代次數;

達夫設備:

var iterations = Math.floor(items.length/8);

startAt = items.length % 8;

i = 0;

do {

    switch(startAt) {

        case 0 : process(items[i++]);

        case 7 : process(items[i++]);

        case 6 : process(items[i++]);

        case 5 : process(items[i++]);

        case 4 : process(items[i++]);

        case 3 : process(items[i++]);

        case 2 : process(items[i++]);

        case 1 : process(items[i++]);

}

startAt = 0;

} while(-- iterations);

  1. 基於函數的迭代

forEach()

比基於循環的迭代要慢:每一個數組項要關聯額外的函數調用;

關注執行時間的狀況下它並非一個合適的方法;

  1. 條件表達式

大多數狀況下,switch比if-else更快,但只有當條件體數量很大時才明顯;

二者區別:條件體增長時,if-else性能負擔增長程度比switch多;

優化if-else:

條件體應當老是按照從最大機率到最小几率的順序排列,保證理論運行速度更你快;

嵌套使用;

 

  1. 查表法

最經常使用於一個鍵和一個值造成邏輯映射領域

 

  1. 遞歸

遞歸函數會遇到瀏覽器調用棧大小的限制

 

5、      字符串和正則表達式

  1. 優化字符串鏈接

「+」,

「+=」,

Array.join(),

String.concat(),

 

str = str + 「one」 + 「two」;

避免了使用臨時字符串

  1. 數組聯結
  2. 正則表達式優化

工做原理:

第一步:編譯

第二步:設置起始位置

第三步:匹配每一個正則表達式的字元

第四步:匹配成功或失敗

6、      響應接口

  1. 瀏覽器UI線程

JavaScript和UI更新共享的進程被稱爲瀏覽器UI進程;

瀏覽器在JavaScript運行時間上採起了限制:

調用棧尺寸限制和長時間腳本限制;

  1. 用定時器讓出時間片

setTimeout()和setInterval()

第二個參數指出是麼時候應當將任務添加到UI隊列之中,並非說那時代碼被執行;

  1. 分解任務
  2. 限時運行代碼
  3. Web Work

不綁定UI線程,不能訪問許多瀏覽器資源。

7、Ajax異步JavaScript和XML

相關文章
相關標籤/搜索