標籤:設定 ima javascrip 資料格式 文檔 res oca java tar
一:載入和執行
1.<script>標籤放在頁面底部,</body>閉合標籤之前,這能確保在指令碼執行前頁面已經完成渲染。
2.合并指令碼。頁面中<script>標籤越少載入越快。
3.無阻塞下載指令碼:defer(消極式載入)、async(非同步載入)、動態建立<script>元素下載並執行、使用XHR對象下載js代碼並注入頁面中。
二、資料存取
四種基本資料存放區方式:字面量(基本類型:字串、數字、布爾值、對象、數組、函數、正則式,直接賦值不用new的等式右邊的值)、變數、數組項、對象成員。
1.訪問字面量和局部變數最快,訪問數組和對象成員相對較慢。
2.局部變數在範圍鏈的起始位置,因此訪問局部變數比訪問跨範圍變數更快。
3.避免使用with語句,它會改變執行環境範圍鏈,變數深度有變。
4.嵌套的對象成員少用,會明顯影響效能。執行location.href 比Window.location.href快。
5.屬性或方法在原型鏈中的位置越深,訪問它速度越慢。
通常來說,可以把常用的對象成員、數組元素、跨域變數儲存在局部變數中來改善js效能,因為局部變數訪問速度更快。
對象字面量比new Object()更高效:{}字面量可立即求值,而new Object()本質上是方法調用,所以需要範圍解析,找到同名函數後建立對象。
對象字面量vs建構函式建立對象對比(字面量優勢):
a.它的代碼量更少,更易讀;
b.它可以強調對象就是一個簡單的可變的散列表,而不必一定派生自某個類;
c.對象字面量運行速度更快,因為它們可以在解析的時候被最佳化:它們不需要"範圍解析(scope resolution)";因為存在我們建立了一個同名的建構函式Object()的可能,當我們調用Object()的時候,解析器需要順著範圍鏈從當前範圍開始尋找,如果在當前範圍找到了名為Object()的函數就執行,如果沒找到,就繼續順著範圍鏈往上找,直到找到全域Object()建構函式為止
d.Object()建構函式可以接收參數,通過這個參數可以把對象執行個體的建立過程委託給另一個內建建構函式,並返回另外一個對象執行個體,而這往往不是你想要的。
//對象直接量定義var o = { propertyfun: function ([parameters]) {}, get property() {}, set property(value) {},};
通過對象字面量和建構函式建立對象的區別: 1190000008462406
三:DOM操作
1.最小化DOM訪問次數,儘可能在JS端處理。(DOM渲染引擎和js引擎是獨立的,互動消耗效能)如遍曆.innerHTML+=‘a’賦值時,可先把’aa..’內容合并然後一次性賦值。
2.如果需要多次訪問某個DOM節點,使用局部變數儲存它的引用。
3.小心處理HTML集合(如document.images,document.links 返回a元素),因為它即時聯絡著底層文檔。如果需要遍曆時,集合長度緩衝到變數,如果需要經常操作集合,可以複製到一個數組中。DOM標準中HTML集合以一種“假定即時態”即時存在,當底層文檔對象更新時,它也會自動更新,即使擷取集合元素個數也會執行詢問過程。
4.如果可能的話,使用速度更快的API,如queryselectorall(返回NodeList ,返回的不是HTML集合,因此返回的節點不會對應即時的文檔結構。而 document.getElementById()是HTML集合,需要把它拷貝到數組中才能得到類似qall類似的靜態列表)和firstElementChild
5.注意重繪(非幾何屬性變化後引起。)和重排(幾何屬性和頁面配置改變時。重排最佳化:通過隊列化修改並批量執行來最佳化重排過程,但部分方法會強制重新整理渲染隊列,如offsetTop位移量/scrollLeft滾動位置/clientWidth系列和計算出樣式值getComputedStyle/currentStyle):最小化重排和重繪“”合并多次對DOM和樣式的修改;批量修改樣式時,“離線”操作Dom樹(脫離文檔:display,文檔片段,複製節點),使用緩衝布局資訊(位移量等),並減少訪問局部資訊的次數。
6.動畫中使用絕對位置(減少重新整理渲染隊列),使用拖放代理()
7.使用事件委託(target/scrElement)來減少事件處理器的數量。
四:演算法和流程式控制制
1. 在判斷條件較多時,使用尋找表比if-else和switch更快。
2. 瀏覽器調用棧大小限制了遞迴演算法在js中的應用,棧溢出會導致代碼中斷。可改為迭代演算法或Memoization(緩衝運算結果的方法)來避免重複計算。
五:字串和Regex
1.不考慮IE7數組項合并是比較慢的字串串連方法,可用簡單的+和+=操作符替代,避免不必要的中間字串(IE除外,其他瀏覽器器會嘗試為運算式左側的字串分配更多的記憶體,然後簡單將第二個字串拷貝到它的末尾。如果迴圈中基礎字串位於最左端,可以避免重複拷貝一個逐漸層大的基礎字串例: str +=’one’;str +=’two’可使用str=str+’one’+’two’提升效能,str作為基礎,每次給它附加一個字串。.但如果str =’one’+str+’two’最佳化失效)。
2.正則式處理好回溯問題
六:快速響應的使用者介面
1.任何js任務都不應當執行超過100毫秒。過長已耗用時間導致UI更新出現明顯遲緩影響使用者體驗。
2.可使用定時器分解大任務為小任務後執行,或使用WebWorker,它允許在UI線程外執行js代碼,從而避免鎖定UI。
七:快速響應的使用者介面
1.選擇正確的資料格式:純文字和html只適用於特定場合,可節省用戶端CPU周期;XML支援良好但它十分笨重且解析緩慢;JSON輕量級,解析速度快;字元分隔自訂格式十分輕量級,在解析大量資料集時非常快,但需要編寫額外的服務端構造程式,並在用戶端解析。
2.資料請求方式
XMLHttpRequest(XHR):不能從外域請求資料,從伺服器端返回的資料被當做字串或XML,這意味著處理大量資料將會很慢。不改變伺服器狀態,只擷取資料的請求使用get,使用Get請求的資料會被緩衝起來。參數超過2048個字元可使用POST請求。
Dynamic script tag insertion動態指令碼注入:可跨域請求 var el=document.createElement(‘script‘);el.src=’’;(‘head’)[0].appendChild(el);
缺點:不能佈建要求頭,只能用get方式,不能佈建要求逾時處理或重試,是否失敗也不一定知道。響應訊息作為指令碼標籤的源碼,它必須是可執行檔js代碼。
Iframes
Comet:
Beacons:類似動態指令碼注入,使用js建立Image對象,把src設定為伺服器上的指令碼url。適合發送少量資料返回資訊不太重要
var beacon= new Image();beacon.src=url+’?key1=value1’;beacon.onload=function(){ if(this.width==1){//如約定返回圖片寬度為1表示成功2表示重試,如果無需返回資料返回一個204 no content 它將阻止用戶端繼續等待永遠不會到來的訊息本文 }else if(this.width==2){//2否則重試}} beacon.onerror=function(){}
Multipart XHR:允許用戶端只用一個http請求就可以從服務端向用戶端傳送多個資源。資料不能緩衝
註:任何資料類型都可以被js作為字串發送。
3.減少請求數,可通過合并js、css檔案或使用MXHR;
4.縮短頁面載入時間,頁面主要內容載入完成後,用ajax擷取次要檔案
八:編程實踐
1.避免使用eval和Funciton構造器來避免雙重求值(在js代碼中執行另一段代碼,此時首先會以正常方式求值,然後在執行過程中對包含字串中的代碼發起另一個求值運算)帶來的效能消耗。給setTimeout和setInterval傳遞函數而不是字串作為參數
2.避免重複工作(事件處理的相容函數)。當需要檢測瀏覽器時,可使用消極式載入(指令碼調用時檢測)和條件預先載入(指令碼載入期間提前檢測)。
消極式載入:
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)}
3.在進行數學計算時考慮使用自己運算元字的二進位形式的位元運算
4.盡量使用原生方法。
九:構建並部署高效能js應用
1.合并js檔案減少http請求量
2.壓縮js檔案
3.在服務端壓縮js檔案(Gzip編碼)
4.通過正確設定http回應標頭來緩衝js檔案,通過改變檔案名稱的方式強制瀏覽器重新載入指定檔案
5.使用CDN(content Delivery networtk)內容分髮網絡提供js檔案;CDN不僅可以提升效能,還能管理檔案的壓縮與緩衝。
十:構建並部署高效能js應用
1.使用網路分析工具找出載入指令碼和頁面中其他資源的瓶頸,協助決定哪些指令碼需要消極式載入等
2.盡量減少http請求數,把指令碼儘可能消極式載入
3.使用效能分析工具找出指令碼運行過程中速度較慢的地方,檢查每個函數所消耗的時間以及函數被調用的次數,通過調用棧自身提供的線索來找出需要集中精力最佳化的地方
其他:
應用實踐中代碼最佳化,提取重用函數,重用組件等。
高效能JavaScript--讀書筆記