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中用到的周遊方法,有些地方描述的不是特别清晰,可能還存在誤人子弟的地方,如果有大佬發現了還望及時指出,自已發現了也會及時更新的。
對于周遊,可能還有其他辦法,以後發現了會繼續記錄。
作者:喬二哥
加班碼字不易 文章暫不允許私自轉載,轉載請在明顯的地方标注文章出處。
轉載于:https://www.cnblogs.com/qiaoge0923/p/9594539.html