首先,由於js是一種解釋型語言,執行速度要比編譯型語言慢得多。(注:,chrome是第一款內建優化引擎,將js編譯成本地**的瀏覽器,其它瀏覽器也陸續實現了js的編譯過程。但是,即使到了編譯執行js的新階段,仍然會存在低效率的**。)以下總結一些可以改進**的整體效能的方法。
記住一點,隨著作用域中的作用域數量的增加,訪問當前作用域以外的變數的時間也在增加。所以,訪問全域性變數總是比訪問區域性變數要慢,因為需要遍歷作用域鏈。只要能減少花費在作用域鏈上的時間,就能增加指令碼的整體效能。
1). 避免全域性查詢(因為涉及作用域上的查詢)
function updateui(
)}
注意,updateui中包含了二個對於全域性變數document物件的引用,特別是迴圈中的document引用,查到次數是o(n),每次都要進行作用域鏈查詢。通過建立乙個指向document的區域性變數,就可以通過限制一次全域性查詢來改進這個函式的效能。
function updateui(
)}
2). 避免with語句(with會建立自已的作用域,因此會增加其中執行**的作用域的長度)
和其它語言一樣,效能問題的一部分是和用於解決問題的演算法或方法有關的,所以通過選擇正確的方法也能起到優化作用。
在js中訪問變數或陣列都是o(1)操作,比訪問物件上的屬性更有效率,後者是乙個o(n)操作。物件上的任何屬性查詢都要比訪問變數或陣列花費更長時間,因為必須在原型鏈中對擁有該名稱的屬性進行一次搜尋,即屬性查詢越多,執行時間越長。所以針對需要多次用到物件屬性,應將其儲存在區域性變數。
迴圈是程式設計中最常見的結構,優化迴圈是效能優化過程中很重要的一部分。乙個迴圈的基本優化步驟如下:
減值迭代——大多數迴圈使用乙個從0開始,增加到某個特定值的迭代器。在很多情況下,從最大值開始,在迴圈中不斷減值的迭代器更加有效。
簡化終止條件——由於每次迴圈過程都會計算終止條件,故必須保證它盡可能快,即避免屬性查詢或其它o(n)的操作。
簡化迴圈體——迴圈體是執行最多的,故要確保其被最大限度地優化。確保沒有某些可以被很容易移出迴圈的密集計算。
使用後測試迴圈——最常用的for和while迴圈都是前測試迴圈,而如do-while迴圈可以避免最初終止條件的計算,因些計算更快。
for
(var i =
0; i < values.length
; i++
)
優化1:簡化終止條件
for
(var i =
0, len = values.length
; i < len; i++
)
優化2:使用後測試迴圈(注意:使用後測試迴圈需要確保要處理的值至少有乙個)
var i values.length-1
;if(i >-1
)while(
--i >=0)
;}
當迴圈的次數確定時,消除迴圈並使用多次函式呼叫往往更快
當迴圈的次數不確定時,可以使用duff裝置來優化。duff裝置的基本概念是通過計算迭代的次數是否為8的倍數將乙個迴圈展開為一系列語句。如下:
// jeff greenberg for js implementation of duff's device
// 假設:values.length > 0
function process(v)
var values =[1
,2,3
,4,5
,6,7
,8,9
,10,11
,12,13
,14,15
,16,17
];var iterations =
math.ceil
(values.length/8
);var startat = values.length%8
;var i =0;
do startat =0;
}while(
--iterations >0)
;
如上展開迴圈可以提公升大資料集的處理速度。接下來給出更快的duff裝置技術,將do-while迴圈分成2個單獨的迴圈。(注:這種方法幾乎比原始的duff裝置實現快上40%。)
// speed up your site(new riders, 2003)
function process(v)
var values =[1
,2,3
,4,5
,6,7
,8,9
,10,11
,12,13
,14,15
,16,17
];var iterations =
math.floor
(values.length/8
);var leftover = values.length%8
;var i =0;
if(leftover >0)
while(
--leftover >0)
;}dowhile(
--iterations >0)
;
針對大資料集使用展開迴圈可以節省很多時間,但對於小資料集,額外的開銷則可能得不償失。
當js**想解析js**時就會存在雙重解釋懲罰,當使用eval()函式或是function建構函式以及使用settimeout()傳乙個字串時都會發生這種情況。如下
eval(
"alert('hello world');");
// 避免
var sayhi =
newfunction
("alert('hello world');");
// 避免
settimeout(
"alert('hello world');"
,100);
// 避免
以上**是包含在字串中的,即在js**執行的同時必須新啟運乙個解析器來解析新的**。例項化乙個新的解析器有不容忽視的開銷,故這種**要比直接解析要慢。以下這幾個例子,除了極少情況下eval是必須的,應盡量避免使用上述。對於function建構函式,直接寫成一般的函式即可。對於settimeout可以傳入函式作為第乙個引數。如下:
alert(
'hello world');
var sayhi =
function()
;settimeout(
function()
,100
);
總之,若要提高**效能,盡可能避免出現需要按照js解釋的**。
原生方法更快——只要有可能,使用原生方法而不是自已用js重寫。原生方法是用諸如c/c++之類的編譯型語言寫出來的,要比js的快多了。
switch語句較快——若有一系列複雜的if-else語句,可以轉換成單個switch語句則可以得到更快的**,還可以通過將case語句按照最可能的到最不可能的順序進行組織,來進一步優化。
位運算較快——當進行數**算時,位運算操作要比任何布林運算或算數運算快。選擇性地用位運算替換算數運算可以極大提公升複雜計算的效能,諸如取模,邏輯與和邏輯或也可以考慮用位運算來替換。
js**中的語句數量也會影響所執行的操作的速度,完成多個操作的單個語句要比完成單個操作的多個語句塊快。故要找出可以組合在一起的語句,以減來整體的執行時間。這裡列舉幾種模式
// 避免
var i =1;
var j =
"hello"
;var arr =[1
,2,3
];var now =
newdate()
;// 提倡
var i =1,
j ="hello"
, arr =[1
,2,3
],now =
newdate()
;
// 避免
var name = values[i]
;i++;
// 提倡
var name = values[i++
];
// 避免
var a =
newarray()
;a[0]
=1;a[
1]="hello";a[
2]=45
;var o =
new obejct();
o.name
="bill"
;o.age=13
;// 提倡
var a =[1
,"hello",45
];var o =
;
在js中,dom無疑是最慢的一部分,dom操作和互動要消耗大量時間,因為它們往往需要重新渲染整個頁面或者某乙個部分,故理解如何優化與dom的互動可以極大提高指令碼完成的速度。
一旦你需要訪問的dom部分是已經顯示的頁面的一部分,那麼你就是在進行乙個現場更新。之所以叫現場更新,是因為需要立即(現場)對頁面對使用者的顯示進行更新,每乙個更改,不管是插入單個字元還是移除整個片段,都有乙個效能懲罰,因為瀏覽器需要重新計算無數尺寸以進行更新。現場更新進行的越多,**完成執行所花的時間也越長。
當使用innerhtml設定為某個值時,後台會建立乙個html直譯器,然後使用內部的dom呼叫來建立dom結構,而非基於js的dom呼叫。由於內部方法是編譯好的而非解釋執行,故執行的更快。
最佳實踐React效能優化
1 基本使用 使用方法 import react,from react import from utils const loadinghome dynamic import components home const loadinguser dynamic import components use...
MySQL 的效能優化最佳實踐
資料庫操作是當今 web 應用程式中的主要瓶頸。不僅是 dba 資料庫管理員 需要為各種效能問題操心,程式設計師為做出準確的結構化表,優化查詢效能和編寫更優 也要費盡心思。在本文中,我列出了一些針對程式設計師的 mysql 優化技術。在我們開始學習之前,我補充一點 你可以在 envato marke...
Python C擴充套件實踐 效能對比
因為效能等一些原因,希望用c來擴充套件python。有多種方法,例如 這裡闡述最後一種方式的實現。首先需要 include 需要實現下面三個函式 static pyobject funcname pyobject self,pyobject args 函式定義 static pymethoddef ...