js 總結之數組的遍歷方式


js中數組的遍歷方式

for

for 循環遍歷是最普通的一種方式,通過數組中自帶的索引進行數組元素的獲取,這種方式可以支持 break、continue、return的打斷形式。具體如下:

for (var i = 0; i < arr.length; i++) {
	// 通過索引進行數組元素的獲取
	console.log(arr[i])
	if (i === 3) {
		// 可以使用break跳出當前循環 效果跟 return 一樣
		break
		// return
	} else if (i === 2) {
		// 可以使用continue跳過當次循環
		continue
	}
}

forEach

forEach是一個方法,這個方法是在 Array 類的 prototype 上,所以所有的Array的實例上都有這個方法。forEach方法沒有返回值,參數有兩個。形式為:arr.forEach(callbackFn[, thisValue]),其中 callbackFn 是個函數,這個函數有三個參數,可以分別記為 item、index、array,見名知意:第一個參數 item 表示的是被遍歷的數組每一項,index 表示的是當前被遍歷項的數組下標,array 表示的是被遍歷的數組對象,此處即為arrcallbackFn 是必傳參數。forEach函數還有一個可傳參數 thisValue,這個參數是一個對象,作用是在 callbackFn 函數中this的引用。如果不傳 thisValue,則默認值為 undefined

注意點:

  1. forEach不能被break、continue、return打斷;
  2. 如果callbackFn是箭頭函數,則傳入的 thisValue 不起作用,因為箭頭函數綁定的this是模塊this
var arr1 = [1, 2, 3]
var arr2 = ['a', 'b', 'c']
arr1.forEach(function(item, index, array) {
	// 這個函數內的this指向arr2
	// item 是arr1數組中的每一項
	// index 是arr1數組的索引值,Number類型
}, arr2)

for in

for in 不僅遍歷數組還可以遍歷對象(當然,數組也是一種特殊的對象),for in 有如下的特點:

  1. 跟 forEach 一樣不能被break、continue、return打斷;
  2. 可以遍歷對象的屬性;
  3. 遍歷的對象屬性包含構造函數的 prototype 上添加的屬性和當前實例上添加的屬性(可以通過 Object.prototype.hasOwnProperty 方法進行區分是不是當前實例的屬性)

具體以實例說明如下:

典型使用方式

var arr = [1, 2, 3, 4]
for (var attr in arr) {
	// 數組索引
	console.log(attr) // 輸出的結果為 0, 1, 2, 3
	// 數組value
	console.log(arr[attr]) // 輸出的結果為 1, 2, 3, 4
}

遍歷Array.prototype 上添加的屬性

Array.prototype.addProperty = 'myadd'
var arr = [1, 2, 3, 4]
for (var attr in arr) {
	console.log(attr) // 輸出的結果為 0, 1, 2, 3, addProperty
}

遍歷實例上添加的屬性

var arr = [1, 2, 3, 4]
arr.instanceProperty = 'myadd'
for (var attr in arr) {
	console.log(attr) // 輸出結果為 0, 1, 2, 3, instanceProperty
}

通過 hasOwnProperty 進行屬性的區分

Array.prototype.addProperty = 'add'
var arr = [1, 2, 3, 4]
arr.instanceProperty = 'myadd'
for (var attr in arr) {
	if (arr.hasOwnProperty(attr)) {
		console.log(attr) // 輸出結果為 0, 1, 2, 3, instanceProperty
	}
	console.log(attr) // 輸出結果為 0, 1, 2, 3, instanceProperty, addProperty
}

for of

for of 是 es6中新增的語句,用於遍歷迭代器,也就是說只要實現了iterator接口的實例都能被for of所迭代。在js對象中實現了iterator接口的有:String、Array、Map、Set、Generator、通過計算生成的entries|keys|values、類數組對象arguments|DOMList,由於Object沒有實現iterator接口,所以不能通過for of進行迭代。數組的迭代器方法可以通過Array.prototype[Symbol.iterator]找到。for of有如下特點:

  1. 跟for循環一樣可以被break、continue、return打斷;
  2. 不能遍歷到Array原型上的屬性;
  3. 不能遍歷到數組實例上添加的屬性;
  4. for of 只能遍歷到數組的value,而不能得到數組的索引

具體實例說明如下:

典型用法

var arr = [1, 2, 3, 4]
// arr 上添加屬性
arr.addProperty = 'add'
// Array.prototype 上添加屬性
Array.prototype.addPro = 'test'
for(var attr of arr) {
	if (attr === 3) {
		continue
	}
	console.log(attr)  // 輸出結果:1, 2, 4
	// 不能遍歷到addProperty、addPro
}

map

map的用法跟forEach非常的類似,跟forEach一樣都是 Array.ptototype 上的方法,通過原型鏈,所有的Array實例都可以訪問到map方法。map方法的參數跟forEach一樣,一個回調函數和一個this對象:arr.map(callbackFn[, thisValue]),並且callbackFn的參數跟forEach中的callbackFn中的參數也是一樣的。map跟forEach的區別在於,map是有返回值的,返回值是一個新的數組實例。map方法的目標並不是用來對原數組進行遍歷,而是在原數組的基礎上進行一些變換從而得到一個新的數組。這些變換並不會影響到原數組。下面看一下map方法的典型用法:

var arr = [1, 2, 3, 4]
// map 方法有返回值,返回值是一個新的數組
var arr2 = arr.map(function(curValue, index, ar) {
	// callbackFn 也需要返回值,返回值會成為新數組的子項。與原數組一一對應
	return curValue * 2
})
console.log(arr)
// 輸出結果為:[1, 2, 3, 4]
console.log(arr2)
// 輸出結果為:[2, 4, 6, 8]

forEach和map的 callbackFn中雖然可以得到被遍歷數組的每一項,但是我們如果要改變原數組需要使用一點手段。callbackFn方法的參數傳入同普通方法的參數一樣,都是將數據的引用傳入到了函數中。所以我們如果直接更改參數的引用的話,我們將不能變更原數組的內容。如下例所示:

var arr = [1, 2, 3, 4]
arr.map(function(curVal, index, ar) {
	curVal *= 2
})
console.log(arr) // 輸出結果 1, 2, 3, 4

上面的做法並不能改變原數組,因為curVal是一個引用,我們在callbackFn中將curVal的引用重新進行了賦值,引用的指向改變了。所以arr中對應的值並不會發生改變,因為arr中對應的值的引用與curVal的引用指向已經不一樣了。我們把實例改一下:

var arr = [
	{value: 1},
	{value: 2},
	{value: 3},
	{value: 4}
]
arr.map(function(curVal, index, ar) {
	curVal.value *= 2	
})
console.log(arr) // 輸出結果為:[{value: 2}, {value: 4}, {value: 6}, {value: 8}]

這里我們將 curVal.value 的引用重新指向,但是curVal的指向並沒有被修改,也就是說 curVal 的引用指向還是跟 arr 中對應項的引用指向保持一致,所以最終輸出的結果會發生變化。還有一種做法,我們利用第二個和第三個參數來修改原來的數組:

var arr = [1, 2, 3, 4]
arr.map(function(curVal, index, ar) {
	ar[index] *= 2	
})
console.log(arr) // 輸出的結果為:2, 4, 6, 8

forEach 的效果同map

every

every 類似 forEach和map,都是 Array.prototype上的方法,該方法的返回值是boolean,callbackFn的返回值也是一個boolean,如果為true則繼續遍歷,直到返回值為false或者到達數組邊界結束遍歷。every方法常用來判斷當前數組中所有項是否滿足指定條件。

var arr = [1, 2, 3, 4, 5]
var b1 = arr.every(function(curVal) {
	return curVal < 10	
})
var b2 = arr.every(function(curVal) {
	return curVal < 4	
})
console.log(b1) // 結果為 true
console.log(b2) // 結果為 false

iterator

iterator 是一個方法,Array 構造函數的原型上通過 Symbol.iterator 指向這個方法。該方法執行的到結果是一個 Iterator 對象,通過 Object.prototype.toString.call(arr[Symbol.iterator]) 得到的結果是 "object Array Iterator"。所有的 數組實例都可以直接通過 Symbol.iterator 獲得 iterator 方法。我們可以通過 iterator 進行數組的遍歷。具體代碼如下:

var arr = [1, 2, 3, 4]
var it = arr[Symbol.iterator]()
var item = null
while(!(item = it.next()).done) {
	console.log(item.value) // 結果: 1, 2, 3, 4
}

除了通過next方法進行遍歷之外,我們還能使用 for of 來遍歷iterator

var arr = [1, 2, 3, 4]
var it = arr[Symbol.iterator]()
for (var attr of it) {
	console.log(attr) // 結果:1, 2, 3, 4
}

關於iterator的詳細內容參見 Iterator阮老師博客

keys、values、entries

這三個方法是 es6 中新增的,返回值是一個 iterator。得到 iterator 之后就可以使用 iterator 的遍歷方式進行遍歷。三個方法略有區別:

keys:通過keys方法得到的iterator可以遍歷數組的索引值

var arr = [1, 2, 3, 4]
var keys = arr.keys()
for (var attr of keys) {
	// 輸出的是數組的索引值
	console.log(attr) // 結果:0, 1, 2, 3
}

values:通過values方法得到iterator,可以遍歷到一個對象,對象的形式為:{value: 1}。鍵為固定的value,值是對應的數組值。

var arr = [1, 2, 3, 4]
var values = arr.values()
for (var attr of values) {
	// 輸出的是數組的索引值
	console.log(attr) // 結果:{value: 1}, {value: 2}, {value: 3}, {value: 4}
}
// 通過結構的方式
for (var { value } of values) {
	// 輸出的是數組的索引值
	console.log(value) // 結果:1, 2, 3, 4
}

entries:通過values方法得到iterator,可以遍歷到一個數組,數組的形式為:[index, value]。數組的第一項是被遍歷數組的索引,數組的第二項是被遍歷數組的值。

for (var attr of [1, 2, 3, 4].entries()) {
	console.log(attr) // 結果為:[0, 1], [1, 2], [2, 3], [3, 4]
}
// 通過解構的方式進行遍歷
for (var [index, value] of [1, 2, 3, 4].entries()){
	console.log(index) // 結果為 0, 1, 2, 3
	console.log(value) // 結果為 1, 2, 3, 4
}

(完)


免責聲明!

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



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