JS之for迴圈優化
阿新 • • 發佈:2019-02-16
眾所周知Js中的迴圈大致可以分為4中:
1.for迴圈
Javascript程式碼
其中for迴圈是最常見的迴圈結構,由四部分組成:初始化、前測條件、後執行體、迴圈體。當代碼執行遇到for迴圈時,先執行初始化程式碼,然後進入前側條件。如果前側條件為true,則執行迴圈體。迴圈體執行完後,後執行程式碼開始執行。
2. while 迴圈
while迴圈是最簡單的前測迴圈,有一個前測條件和一個迴圈體構成:
Javascript程式碼
3. do..while迴圈
do-while 迴圈是js中唯一一種後測迴圈,由兩部分組成,迴圈體和後測條件
Javascript程式碼
在do-while中至少會執行一次迴圈體
4 for-in迴圈
該迴圈有一個特別的用途:可以列舉任何物件的屬性名。
Javascript程式碼
迴圈體每次執行時,prop變數被賦值為object的一個屬性名,直到所有屬性遍歷完成才返回。所返回的屬性包括物件例項屬性和從原型鏈中繼承而來的屬性
以後對4中迴圈進行了大致的介紹,接下來說說如何在進行相關係能提升
4中迴圈型別中,只有for-in迴圈比其他幾種明顯要慢:主要原因在於每次迭代操作會同時搜尋例項或原型屬性,每次迭代都會產生更多開銷。
如果迴圈型別與效能無關,可以從以下兩個可選因素來提高整體效能
1.每次迭代處理的事務
2.迭代的次數
減少迭代的工作量
很明顯,如果一次迴圈迭代要花很長時間去執行,那麼多次迴圈需要花更多的時間。一個提升迴圈整體速度的好方法就是限制迴圈中耗時的運算元量。
一個典型的陣列處理迴圈可以採用三種迴圈中的任何一種。最常見的寫法如下:
Javascript程式碼
上面的每個迴圈中,每次進行迴圈體時都會產生如下操作:
1. 一次控制條件中的屬性查詢(items.length)
2. 一次控制條件中的數值大小的比較(i<items.length)
3. 一次控制條件結果是否為true的比較(i<items.length == true)
4. 一次自增操作(i++)
5. 一次陣列查詢(items[i])
6. 一次函式呼叫( process(items[j]);)
這些簡單迴圈中,儘管程式碼不多,但每次迭代都要進行許多操作。程式碼執行速度很大晨讀上取決於函式process()對每個陣列項的操作,儘管如此,減少每次迭代中的操作能大幅提高迴圈的整體效能。
優化迴圈的第一步就是減少物件成員及陣列項的查詢次數。前面例子中每次迴圈都要查詢items.length,這樣做很耗時,由於該值在迴圈執行過程中從未變過,因此產生了不必要的效能損失,提高整個迴圈的效能很簡單,只查詢一次屬性,並把值儲存到一個區域性變數中,然後在控制條件中使用整個變數
Javascript程式碼
還可以通過倒序迴圈來進行。
減少迭代次數
即使是迴圈體中最快的程式碼,累計迭代上千次也會慢下來。此外,迴圈體執行時也會帶來小效能開銷,不僅僅是增加總體執行時間。減少迭代次數能獲得更加顯著的效能提升。下面介紹一種廣為人知的限制迴圈迭代次數的模式被稱為“達夫裝置(Duff's Device)”:
Duff's Device 是一個迴圈體展開技術,使得一次迭代實際執行了多次迭代的操作
Javascript程式碼
1.for迴圈
Javascript程式碼
- for(var i=0;i<10;i++){
- //迴圈主題
- }
其中for迴圈是最常見的迴圈結構,由四部分組成:初始化、前測條件、後執行體、迴圈體。當代碼執行遇到for迴圈時,先執行初始化程式碼,然後進入前側條件。如果前側條件為true,則執行迴圈體。迴圈體執行完後,後執行程式碼開始執行。
2. while 迴圈
while迴圈是最簡單的前測迴圈,有一個前測條件和一個迴圈體構成:
Javascript程式碼
- var i = 0;
- while(i < 10){
-
//迴圈主題
- i++;
- }
3. do..while迴圈
do-while 迴圈是js中唯一一種後測迴圈,由兩部分組成,迴圈體和後測條件
Javascript程式碼
- var i = 0;
- do{
- //迴圈體
- }while(i++ < 10)
在do-while中至少會執行一次迴圈體
4 for-in迴圈
該迴圈有一個特別的用途:可以列舉任何物件的屬性名。
Javascript程式碼
- for(var prop in object){
- //迴圈體
- }
迴圈體每次執行時,prop變數被賦值為object的一個屬性名,直到所有屬性遍歷完成才返回。所返回的屬性包括物件例項屬性和從原型鏈中繼承而來的屬性
以後對4中迴圈進行了大致的介紹,接下來說說如何在進行相關係能提升
4中迴圈型別中,只有for-in迴圈比其他幾種明顯要慢:主要原因在於每次迭代操作會同時搜尋例項或原型屬性,每次迭代都會產生更多開銷。
如果迴圈型別與效能無關,可以從以下兩個可選因素來提高整體效能
1.每次迭代處理的事務
2.迭代的次數
減少迭代的工作量
很明顯,如果一次迴圈迭代要花很長時間去執行,那麼多次迴圈需要花更多的時間。一個提升迴圈整體速度的好方法就是限制迴圈中耗時的運算元量。
一個典型的陣列處理迴圈可以採用三種迴圈中的任何一種。最常見的寫法如下:
Javascript程式碼
-
for(var i = 0; i < items.length; i++){
- process(items[i]);
- }
- var j = 0;
- while(j < items.length){
- process(items[j]);
- }
- var k = 0;
- do{
- process(items[k]);
- }while(k < items.length);
上面的每個迴圈中,每次進行迴圈體時都會產生如下操作:
1. 一次控制條件中的屬性查詢(items.length)
2. 一次控制條件中的數值大小的比較(i<items.length)
3. 一次控制條件結果是否為true的比較(i<items.length == true)
4. 一次自增操作(i++)
5. 一次陣列查詢(items[i])
6. 一次函式呼叫( process(items[j]);)
這些簡單迴圈中,儘管程式碼不多,但每次迭代都要進行許多操作。程式碼執行速度很大晨讀上取決於函式process()對每個陣列項的操作,儘管如此,減少每次迭代中的操作能大幅提高迴圈的整體效能。
優化迴圈的第一步就是減少物件成員及陣列項的查詢次數。前面例子中每次迴圈都要查詢items.length,這樣做很耗時,由於該值在迴圈執行過程中從未變過,因此產生了不必要的效能損失,提高整個迴圈的效能很簡單,只查詢一次屬性,並把值儲存到一個區域性變數中,然後在控制條件中使用整個變數
Javascript程式碼
- for(var i = 0,len = item.length; i < len; i++){
- process(items[i]);
- }
- var j = 0,
- len = items.length;
- while(j < len ){
- process(items[j]);
- }
- var k = 0,
- num = items.length;
- do{
- process(items[k]);
- }while(k < num);
還可以通過倒序迴圈來進行。
減少迭代次數
即使是迴圈體中最快的程式碼,累計迭代上千次也會慢下來。此外,迴圈體執行時也會帶來小效能開銷,不僅僅是增加總體執行時間。減少迭代次數能獲得更加顯著的效能提升。下面介紹一種廣為人知的限制迴圈迭代次數的模式被稱為“達夫裝置(Duff's Device)”:
Duff's Device 是一個迴圈體展開技術,使得一次迭代實際執行了多次迭代的操作
Javascript程式碼
- 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);