在ES5中常用的10種陣列遍歷方法:
1、原始的for迴圈語句
2、Array.prototype.forEach陣列物件內建方法
3、Array.prototype.map陣列物件內建方法
4、Array.prototype.filter陣列物件內建方法
5、Array.prototype.reduce陣列物件內建方法
6、Array.prototype.some陣列物件內建方法
7、Array.prototype.every陣列物件內建方法
8、Array.prototype.indexOf陣列物件內建方法
9、Array.prototype.lastIndexOf陣列物件內建方法
10、for...in迴圈語句複製程式碼
ES6中新增加了一種:
1.for...of迴圈語句複製程式碼
ES5三種陣列迴圈示例如下:
原始for迴圈語句
Example1
var a = [1,2,3];
for(var i=0;i<a.length;i++){
console.log(a[i]); //結果依次為1,2,3
}複製程式碼
原始for迴圈的優點在於大家都比較熟悉,容易理解,劣勢是寫起來比較繁瑣,需要定義額外更多的變數,所以一下是針對於原始for迴圈的改良的兩種寫法:
var a = [1,2,3];
for(var i=a.length;i--;){
console.log(a[i]); //結果依次為3,2,1
}複製程式碼
var a = [1,2,3];
for(var i = 0,len=a.length; i < len; i++) {
console.log(a[i]); //結果依次為1,2,3
}複製程式碼
注意:以上程式碼可以寫成這樣呢,如果懵逼了的話接著看原始for迴圈的解讀,我們都知道for迴圈包含三個語句塊——>for(語句1;語句2;語句3){被執行的程式碼},其中,語句1一般為變數定義語句(不僅可以只定義一個變數哦),在迴圈開始前執行,而且只執行一次;語句2定義迴圈的是否繼續執行的條件,同樣也是在迴圈開始前執行,語句1之後執行,每次重新開始迴圈都會再次執行;語句3則在迴圈結束之後執行,並且每次結束的時候都會再次執行,這裡要注意的是如果被執行的程式碼中途return出來了那是不會再執行一次語句3的,所以以上程式碼解釋如下:因為i--這個語句在每次迴圈開始前都會再次先用 i 是true和false來判斷是否繼續執行,這裡同樣要注意的是由於i--和--i的區別,這裡由於是i--所以會先判斷i的值再去做‘減減’的操作,所以這裡最後如果列印 i 的值,會發現其實是-1。
陣列內建方法Array.prototype.forEach
Example
var a = [1,2,3];
a.forEach(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3],該引數貌似沒什麼用
})複製程式碼
forEach方法最大的好處就是便於使用,而且不用定義額外的引數變數,但是從效率以及效能角度來說它是劣於原始for迴圈的,而且也不能強制return結束迴圈,原因如下:
**forEach迴圈**一看就是通過**回撥函式**來提供引數的,而回撥函式在JS中是**閉包**的一種,閉包的作用是用來生成**私有作用域**的,所以,每一個回撥函式都是一個**獨立的作用域**,都擁有自己獨立的儲存空間,互不影響,而且內部變數還不及時釋放,這也就是為什麼在能不用閉包的情況下就不要用閉包的原因,而在閉包中return的話,也只是在當前回撥函式中返回了,可是forEach中的其他的回撥函式(閉包)仍然存在,所以,導致return是沒辦法結束迴圈的。下面寫一個forEach迴圈實現例子供大家參考理解:
複製程式碼
Array.prototype.forEachCopy = function(callback){
var arr = this;
for(var i=0;i<arr.length;i++){
callback(arr[i],i,this);
}
}
var a = [1,2,3];
a.forEachCopy(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3]
})複製程式碼
陣列內建方法Array.prototype.map
Example
var a = [1,2,3];
var b = a.map(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3]
return value+1;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為[ 2, 3, 4 ]複製程式碼
map和forEach不同,在forEach中return語句是沒有任何效果的,而map則可以改變當前迴圈的值,並且最終會返回一個新的被改變過值之後的陣列(map如果不用return就和forEach一樣了),由於這個特性,map一般用來處理需要修改某一個陣列的值。map和forEach在其他的方面都是一樣的,也不能return結束迴圈等特性,下面寫一個map迴圈實現的例子供大家參考理解:
Array.prototype.mapCopy = function(callback){
var arr = this;
var arrCopy = [];
for(var i=0;i<arr.length;i++){
var cbValue = callback(arr[i],i,this);
arrCopy.push(cbValue);
}
return arrCopy;
}
var a = [1,2,3];
var b = a.mapCopy(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3]
return value+1;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為[ 2, 3, 4 ]複製程式碼
陣列內建方法Array.prototype.filter
Example
var a = [1,2,3];
var b = a.filter(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3]
if(value === 3){
return false;
}
return true;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為[ 1,2 ]複製程式碼
filter和map不同,map目的是為了改變值,而filter目的是為了去掉不要的值,在迴圈的時候如果返回的是false那麼就表示本次迴圈的不新增該值,返回true則相反是表示要新增到新建的陣列中,下面寫一個filter迴圈實現例子供大家參考:
Example
Array.prototype.filterCopy = function(callback){
var arr = this;
var arrCopy = [];
for(var i=0;i<arr.length;i++){
var cbValue = callback(arr[i],i,this);
if(cbValue){
arrCopy.push(arr[i]);
}
}
return arrCopy;
}
var a = [1,2,3];
var b = a.filterCopy(function(value,key,arr){
console.log(value) // 結果依次為1,2,3
console.log(key) // 結尾依次為0,1,2
console.log(arr) // 三次結果都為[1,2,3]
if(value === 3){
return false;
}
return true;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為[ 1,2 ]複製程式碼
陣列內建方法Array.prototype.reduce
Example
var a = [1,2,3];
var b = a.reduce(function (count, value,key,arry) {
console.log(count); // 結果依次為0,1,3
console.log(value); // 結果依次為1,2,3
console.log(key); // 結果依次為0,1,2
console.log(arry) // 三次結果都為[1,2,3]
return count + value;
},0);
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b) // 結果為6複製程式碼
reduce的不同之處在於累加,和其他幾個內建方法不同的地方,它的第二個引數不是this物件,而是初始累加值(如果不設定的話陣列會亂掉),而且回撥函式的的個數也不同,比其他的多了一個,而且還在在開始的多加了一個引數,第一個引數記錄的是上一次迴圈的累加值,下面寫一個reduce迴圈實現例子供大家參考:
Array.prototype.reduceCopy = function(callback,countInit){
var arr = this;
for(var i=0;i<arr.length;i++){
var cbValue = callback(countInit,arr[i],i,this);
countInit = cbValue;
}
return countInit;
}
var a = [1,2,3];
var b = a.reduceCopy(function (count, value,key,arry) {
console.log(count); // 結果依次為0,1,3
console.log(value); // 結果依次為1,2,3
console.log(key); // 結果依次為0,1,2
console.log(arry) // 三次結果都為[1,2,3]
return count + value;
},0);
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b) // 結果為6複製程式碼
陣列內建方法Array.prototype.some
Example
var a = [1,2,3];
var b = a.some(function(value,key,arry){
console.log(value); // 結果依次為1,2
console.log(key); // 結果依次為0,1
console.log(arry); // 兩次次結果都為[1,2,3]
return value===2;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為true複製程式碼
some的不同之處在它返回的布林值,它的作用有點像filter,不過它的目的不是為了篩選返回陣列,而是為了篩選該陣列是否有滿足你要的值,而且找到符合條件的值返回了一次true之後就不會再繼續執行了,下面寫一個some迴圈實現例子供大家參考:
Array.prototype.someCopy = function(callback,countInit){
var arr = this;
var isBool = false;
for(var i=0;i<arr.length;i++){
var cbValue = callback(arr[i],i,this);
if(cbValue){
isBool = true;
return isBool
}
}
return isBool;
}
var a = [1,2,3];
var b = a.someCopy(function(value,key,arry){
console.log(value); // 結果依次為1,2
console.log(key); // 結果依次為0,1
console.log(arry); // 兩次次結果都為[1,2,3]
return value===2;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為true複製程式碼
陣列內建方法Array.prototype.every
Example
var a = [1,2,3];
var b = a.every(function(value,key,arry){
console.log(value); // 結果依次為1,2
console.log(key); // 結果依次為0,1
console.log(arry); // 兩次次結果都為[1,2,3]
return value===2;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為false複製程式碼
:其實從看例子可以看出來,some和every作用是一樣的,只不過some當找到之後返回的是true,而every找到之後返回的是false而已,下面寫一個every迴圈實現例子供大家參考:
Array.prototype.everyCopy = function(callback){
var arr = this;
var isBool = true;
for(var i=0;i<arr.length;i++){
var cbValue = callback(arr[i],i,this);
if(cbValue){
isBool = false;
return isBool
}
}
return isBool;
}
var a = [1,2,3];
var b = a.everyCopy(function(value,key,arry){
console.log(value); // 結果依次為1,2
console.log(key); // 結果依次為0,1
console.log(arry); // 兩次次結果都為[1,2,3]
return value===2;
})
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為false複製程式碼
陣列內建方法Array.prototype.indexOf
Example
var a = [1,2,3];
var b = a.indexOf(2);
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為1複製程式碼
:對於indexOf方法來說,在陣列迴圈過程中會和傳入的引數比對,如果是比對成功,那麼終止迴圈,返回對比成功的下標,下面寫一個indexOf迴圈實現例子供大家參考:
Array.prototype.indexOfCopy = function(value){
var arr = this;
var index = -1;
for(var i=0;i<arr.length;i++){
if(arr[i] === value){
index = i;
return index
}
}
return index;
}
var a = [1,2,3];
var b = a.indexOfCopy(2);
console.log(a); // 結果為[ 1, 2, 3 ]
console.log(b); // 結果為1複製程式碼
陣列內建方法Array.prototype.lastIndexOf
Example
var a = [1,2,3,1];
var b = a.lastIndexOf(1);
console.log(a); // 結果為[ 1, 2, 3, 1 ]
console.log(b); // 結果為1複製程式碼
:lastIndexOf方法和indexOf作用一致,但查詢方向不同,indexOf是正向查詢,lastIndexOf是你像查詢,找到之後返回成功的下標,下面寫一個lastIndexOf迴圈實現例子供大家參考:
Array.prototype.lastIndexOf = function(value){
var arr = this;
var index = -1;
for(var i=arr.length;i--;){
if(arr[i] === value){
index = i;
return index
}
}
return index;
}
var a = [1,2,3,1];
var b = a.lastIndexOf(1);
console.log(a); // 結果為[ 1, 2, 3 , 1 ]
console.log(b); // 結果為3複製程式碼
小結:對於以上8個陣列的內建方法,forEach方法僅僅只是為了迴圈,並不可以幫你做額外的事情;map方法相當於在迴圈的時候你告訴陣列當前遍歷的這個值需要改成什麼樣,那麼它就會最後給什麼樣的陣列;filter方法相當於在迴圈的時候陣列遍歷一個個物件,並問你這個是不是你要找的值,如果你說是,他就會給你返回一個到新的陣列中,不是他就會剔除;reduce方法相當於迴圈遍歷物件做統計(累加或者累減之類的);some和every方法相當於在遍歷的時候拿著一個個物件問你這個是不是你找的,只要你說了一遍是,那麼他就會給你分別返回的是true和false;indexOf和lastIndexOf方法相當於你告訴它你要找什麼值,找到之後立馬返回給你它的門牌號。
迴圈語句for...in
Example
var a = [1,2,3];
for(var key in a){
console.log(key); //結果為依次為0,1,2
}
var b = {0:1,1:2,2:3};
for(var key in b){
console.log(key); //結果為依次為0,1,2
}複製程式碼
:從結果得知,for...in遍歷陣列的時候是遍歷陣列的下標值,而在遍歷物件的時候遍歷的是key值,所以猜想,陣列在JS中,本質上也是一個以鍵值對形式存在的物件,而為了證明這點,我們做如下一個例子的實驗:
var a = [];
a['b'] = 2;
console.log(a); //結果為[ b: 2 ]
console.log(a[0]); //結果為undefined複製程式碼
我們發現陣列的下標不在對應相應位置的值了,由此可以證明在JS中陣列其實本質上就是一個以下標為key值的物件。
當然對於for...in迴圈語句本身而言,它是一個淺度遍歷物件的迴圈語句,值遍歷第一層節點(當然物件中設定不可列舉的屬性的除外)。
Example
var a = {b:{c:2},d:{c:4}};
for(var key in a){
console.log(key); //結果為依次為b,d
}複製程式碼
ES6迴圈for...of語句
Example
var a = [1,2,3];
for(var value of a){
console.log(value) // 結果依次為1,2,3
}複製程式碼
for...of語句看著有點像for...in語句,但是和for...in語句不同的是它不可以迴圈物件,只能迴圈陣列。