Javascript 10種遍歷方法


 JS遍歷簡述

對於數組,javascript有很多遍歷的方法,for、for in、for of(ES6)、forEach、map、filter、every、some、Jquery的each等等。接下來通過一些例子來對比一下這些方法。示例均使用如下測試數據:

var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];

 

1. for 循環

for循環語句,最基礎的遍歷,以數組的下標為索引,對數組元素進行遍歷。

示例:

 1 function arrFor(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         for (var k = 0; k < arr.length; k++) {
 6             ret += arr[k];
 7         }
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array for 總耗時:" + diff);
11     } catch (e) {
12         console.log("array for 報錯了:" + e.message);
13     }
14 }

 

 結果(Google):

abcdefghijklmnopqrstuvwxyz
array for 總耗時:1.7999999690800905

 

 結果(IE11):

abcdefghijklmnopqrstuvwxyz
array for 總耗時:0.6000000000000085

 

 for 循環不是函數,不存在返回值。

 2. for in

 for in循環不僅可以遍歷數組,還可以遍歷對象,但for in存在一些陷阱,比如它會在遍歷完元素之后,還會對數組或對象的prototype中的屬性進行遍歷,所以,for in 更像是為對象遍歷而設計的。

 示例: 

 1 function arrForIn(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         for (var k in arr) {
 6             ret += arr[k];
 7         }
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array for in 總耗時:" + diff);
11     } catch (e) {
12         console.log("array for in報錯了:" + e.message);
13     }
14 }

  

結果(Google):

abcdefghijklmnopqrstuvwxyz
array for in 總耗時:1.5999999595806003

 

 結果(IE11):

abcdefghijklmnopqrstuvwxyz
array for in 總耗時:0.7000000000000028

 

2.A 陷阱

在此,我們為數組做一點改動,在調用上面定義的 arrForIn 方法前先執行如下語句:

Array.prototype.name="this is a test";

 

結果(Google):

abcdefghijklmnopqrstuvwxyzthis is a test
array for in 總耗時:2.299999992828816

 

 結果(IE11):

abcdefghijklmnopqrstuvwxyzthis is a test
array for in 總耗時:0.5999999999999943

 

可以明顯看到,打印出的字符串后面有 "this is a test",這就是 Array.prototype.name 的值。也就是說,Array 的原型也參與了遍歷,這就給后續的語句埋下了一個炸彈。

當然,針對這種情況,也是有解決辦法的,可以使用對象的hasOwnProperty()方法來避免此問題,通過hasOwnProperty()方法篩選出的都是對象實例自身的屬性,對於像上面這種從Array繼承過來的屬性,該方法將返回false。

修改:

 1 function arrForIn(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         for (var k in arr) {
 6             if (arr.hasOwnProperty(k)) {
 7                 ret += arr[k];
 8             }
 9         }
10         console.log(ret);
11         var diff = performance.now() - st;
12         console.log("array for in 總耗時:" + diff);
13     } catch (e) {
14         console.log("array for in報錯了:" + e.message);
15     }
16 }

 

結果(Google):

abcdefghijklmnopqrstuvwxyz
array for in 總耗時:2.3999999975785613

 

對於數組的遍歷,不提倡 for in

2.B IE兼容性

示例:

 1 function arrForIn(arr) {
 2     try {
 3         //解決IE9不支持performance
 4         if ((window.navigator.userAgent.indexOf("MSIE 9.0") >= 1) && window.performance) {
 5             window.performance.now = function () {
 6                 return ((+new Date()) - performance.timing.navigationStart);
 7             }
 8         }
 9         var ret = '',
10             st = performance.now();
11         for (var k in arr) {
12             ret += arr[k];
13         }
14         console.log(ret);
15         var diff = performance.now() - st;
16         console.log("array for in 總耗時:" + diff);
17     } catch (e) {
18         console.log("array for in報錯了:" + e.message);
19     }
20 }

 

 

IE 10:

abcdefghijklmnopqrstuvwxyz
array for in 總耗時:0.5999999999999943

 

IE 9:

abcdefghijklmnopqrstuvwxyz
array for in 總耗時:1

  

 測試到IE9,都是支持的。 

3. for of (ES6)

ES6中引入了 for ... of 循環,以替代 for...in 和 forEach() ,允許對 Array(數組)、String(字符串)、Maps(映射)、Sets(集合)等可迭代的數據結構進行遍歷。

 1 function arrForOf(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         for(var k of arr) {
 6             ret += k;
 7         }
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array for of 總耗時:" + diff);
11     } catch (e) {
12         console.log("array for of報錯了:" + e.message);
13     }
14 }

需要注意的是:

1、 for(var k of arr) 中的 k ,就是數組 arr 中的元素,而不是數組的下標。

2、 IE 不支持,Edge支持。

 

結果(Google):

abcdefghijklmnopqrstuvwxyz
array for of 總耗時:2.3999999975785613

  

4. forEach

forEach() 方法用於調用數組的每個元素,並將元素傳遞給回調函數。

 1 function arrForEach(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         arr.forEach(function (v, k) {
 6             ret += v;
 7         });
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array forEach 總耗時:" + diff);
11     } catch (e) {
12         console.log("array forEach報錯了:" + e.message);
13     }
14 }

 

 結果(Google): 

abcdefghijklmnopqrstuvwxyz
array forEach 總耗時:1.7000000225380063

 

  結果(IE11):

abcdefghijklmnopqrstuvwxyz
array forEach 總耗時:1

 

注意:

  •  forEach() 對於空數組是不會執行回調函數的。
  • 回調函數  function (v, k) 中的 k 是數組的下標,v 是數組元素值。
  • IE9以下的版本不支持。

 

瀏覽器支持:

 

 5. map

 map() 方法返回一個新數組,數組中的元素為原始數組元素調用函數處理后的值。

 1 function arrMap(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         arr.map(function (v, k) {
 6             ret += v;
 7         });
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array map 總耗時:" + diff);
11     } catch (e) {
12         console.log("array map報錯了:" + e.message);
13     }
14 }

  

結果(Google): 

abcdefghijklmnopqrstuvwxyz
array map 總耗時:1.5999999595806003

 

結果(IE11):

abcdefghijklmnopqrstuvwxyz
array map 總耗時:0.8000000000000114

  

 瀏覽器支持:

 

  •  map() 返回一個新數組。
  •  map() 不會對空數組進行檢測。
  •  map() 不會改變原始數組。

接下來看一下map處理的結果,先修改一下操作:

function arrMap(arr) {
    try
    {
        var newArr = arr.map(function(v, k) {
            return v + 0;
        });
        console.log(arr.join(','));
        console.log(newArr.join(','));
    }
    catch (e)
    {
        console.log("array map報錯了:" + e.message);
    }
}

 

 輸出結果

a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
a0,b0,c0,d0,e0,f0,g0,h0,i0,j0,k0,l0,m0,n0,o0,p0,q0,r0,s0,t0,u0,v0,w0,x0,y0,z0

 

可以看出

  • map()處理后不會改變原有數組
  • 新數組與原數組的元素個數一致

 6. filter

 filter() 方法創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。

 1 function arrFilter(arr) {
 2     try {
 3         var ret = '',
 4             st = performance.now();
 5         arr.filter(function (v, k) {
 6             ret += v;
 7         });
 8         console.log(ret);
 9         var diff = performance.now() - st;
10         console.log("array filter 總耗時:" + diff);
11     } catch (e) {
12         console.log("array filter報錯了:" + e.message);
13     }
14 }

  

 結果(Google): 

abcdefghijklmnopqrstuvwxyz
array filter 總耗時:1.6000000177882612

  

結果(IE11):

abcdefghijklmnopqrstuvwxyz
array filter 總耗時:0.5999999999999943

 

瀏覽器支持:

 

  • filter() 不會對空數組進行檢測。
  • filter() 不會改變原始數組。

 接下來看一下filter處理的結果,先修改一下操作:

function arrFilter(arr) {
    try
    {
        var newArr = arr.filter(function(v, k) {
            return k > 10;
        });
        console.log("arr:" + arr.join(','));
        console.log("newArr:" + newArr.join(','));
    }
    catch (e)
    {
        console.log("array filter報錯了:" + e.message);
    }
}

 

 結果(Google): 

arr:a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
newArr:l,m,n,o,p,q,r,s,t,u,v,w,x,y,z

 

  • filter() 沒有改變原始數組。
  • filter() 返回的新數組是篩選后的結果。

 7. every

every() 方法用於檢測數組所有元素是否都符合指定條件(通過函數提供),返回 boolen。

 1 function arrEvery(arr) {
 2     try {
 3         var st = performance.now();
 4         var ret = arr.every(function (v, k) {
 5             return v.length > 1;
 6         });
 7         console.log(ret);
 8         var diff = performance.now() - st;
 9         console.log("array every 總耗時:" + diff);
10     } catch (e) {
11         console.log("array every報錯了:" + e.message);
12     }
13 }

 

 結果(Google): 

false
array every 總耗時:1.500000013038516

 

結果(IE11):

false
array every 總耗時:0.5

  

瀏覽器支持:

 

  • 如果數組中檢測到有一個元素不滿足,則整個表達式返回 false ,且剩余的元素不會再進行檢測。
  • 如果所有元素都滿足條件,則返回 true。
  •  every() 不會對空數組進行檢測。
  • every() 不會改變原始數組。

 

 8. some

 some() 方法用於檢測數組中的元素是否滿足指定條件(函數提供)。只要有一個元素滿足則返回true,並不再繼續往下判斷。

 1 function arrSome(arr) {
 2     try {
 3         var st = performance.now();
 4         var ret = arr.some(function (v, k) {
 5             return v.length > 1;
 6         });
 7         console.log(ret);
 8         var diff = performance.now() - st;
 9         console.log("array some 總耗時:" + diff);
10     } catch (e) {
11         console.log("array some報錯了:" + e.message);
12     }
13 }

  

  結果(Google): 

false
array some 總耗時:1.6999999643303454

  

 結果(IE11):

false
array some 總耗時:1.1000000000000227

  

 瀏覽器支持:

 

 

  • 如果有一個元素滿足條件,則表達式返回true , 剩余的元素不會再執行檢測。
  • 如果沒有滿足條件的元素,則返回false。
  • some() 不會對空數組進行檢測。
  • some() 不會改變原始數組。

9. JQuery方法 $.each

each() 方法為每個匹配元素規定要運行的函數。JQuery的each方法既可以遍歷數組,也可以遍歷對象。在遍歷對象時可以很容易獲取對象屬性名。

function jqueryEach(obj) {
    try {
        var ret = '',
            st = performance.now();
        $.each(obj, function(k, v) {
            ret += v;
        });
        console.log(ret);
        var diff = performance.now() - st;
        console.log("jquery each 總耗時:" + diff);
    } catch(e) {
        console.log("jquery each報錯了:" + e.message);
    }
}

 


  結果(Google): 

abcdefghijklmnopqrstuvwxyz
jquery each 總耗時:2.8999999922234565

 


 結果(IE11):

abcdefghijklmnopqrstuvwxyz
jquery each 總耗時:0.6999999999999886

 

  • 一般用法為:$(selector).each(function(index,element)) 或者 $.each(obj,function(index,element)) ;回調函數中 index 參數是 對象obj的屬性名(或者 數組obj 的索引),element 參數是 具體的值。
  • 執行 return true 相當於 continue;
  • 執行 return false 相當於 break;

 

10. Object.keys.forEach

Object.keys.forEach() 主要是用於遍歷對象,獲取對象的屬性名,對於遍歷數組意義不大。

function objectKey(obj) {
    try
    {
        var ret = '',
            st = performance.now();
        Object.keys(obj).forEach(function(key, index, arr) {
            ret += obj[key];
        });
        //ES6寫法
        //Object.keys(obj).forEach(k => {
        //    ret += obj[k];
        //}); 
        console.log(ret);
        let diff = performance.now() - st;
        console.log("object key 總耗時:" + diff);
    }
    catch (e)
    {
        console.log("object key 報錯了:" + e.message);
    }
}

 

  結果(Google): 

abcdefghijklmnopqrstuvwxyz
object key 總耗時:1.799999998183921

 


 結果(IE11):

abcdefghijklmnopqrstuvwxyz
object key 總耗時:1.1000000000000227

 

  • Object.keys.forEach 在遍歷時,回調函數的參數 key是屬性名(對於數組,屬性名和索引一一對應),index 是keys數組的索引,arr是keys數組;所以在取值的時候還是用 obj[key]

 

以上列出了10種在js中用到的遍歷方法,有些地方描述的不是特別清晰,可能還存在誤人子弟的地方,如果有大佬發現了還望及時指出,自已發現了也會及時更新的。

對於遍歷,可能還有其他辦法,以后發現了會繼續記錄。

 

作者:喬二哥

加班碼字不易    文章暫不允許私自轉載,轉載請在明顯的地方標注文章出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM