定義
??迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內(nèi)部表示。
描述
??迭代器模式可以把迭代的過程從業(yè)務邏輯中分離出來,在使用迭代器模式之后,即使不關心對象的內(nèi)部構(gòu)造,也可以按順序訪問其中的每個元素。JavaScript內(nèi)置了很多迭代器,如數(shù)組的forEach()、map()、filter()、some()、every()
。
迭代器分類
??迭代器可以分為內(nèi)部迭代器和外部迭代器,它們有各自的適用場景。
【內(nèi)部迭代器】
內(nèi)部迭代器在調(diào)用的時候非常方便,外界不用關心迭代器內(nèi)部的實現(xiàn),跟迭代器的交互也僅僅是一次初始調(diào)用。如下的forEach函數(shù)的內(nèi)部已經(jīng)定義好了迭代規(guī)則,它完全接手整個迭代過程,外部只需要一次初始調(diào)用,但這也剛好是內(nèi)部迭代器的缺點。由于內(nèi)部迭代器的迭代規(guī)則已經(jīng)被提前規(guī)定,下面的forEach函數(shù)就無法同時迭代2個數(shù)組了。
let arr = [1,2,3,4,5]
arr.forEach(function (item,index,arr) {
console.log(item)
})
【外部迭代器】
外部迭代器必須顯式地請求迭代下一個元素。外部迭代器增加了一些調(diào)用的復雜度,但相對也增強了迭代器的靈活性,可以手工控制迭代的過程或者順序。
let Iterator = function( obj ){
let current = 0
let next = function(){
current += 1
}
let isDone = function(){
return current >= obj.length
}
let getCurrItem = function(){
return obj[ current ]
}
return {
next: next,
isDone: isDone,
getCurrItem: getCurrItem
}
}
??外部迭代器雖然調(diào)用方式相對復雜,但它的適用面更廣,也能滿足更多變的需求。內(nèi)部迭代器和外部迭代器在實際生產(chǎn)中沒有優(yōu)劣之分,究竟使用哪個要根據(jù)需求場景而定。
迭代類數(shù)組
??迭代器模式不僅可以迭代數(shù)組,還可以迭代一些類數(shù)組的對象。比如arguments、{"0":'a',"1":'b'}等。無論是內(nèi)部迭代器還是外部迭代器,只要被迭代的聚合對象擁有l(wèi)ength屬性而且可以用下標訪問,那它就可以被迭代。
在JS中,for in語句可以用來迭代普通字面量對象的屬性。jQuery中提供了$.each函數(shù)來封裝各種迭代行為:
$.each = function (obj, callback) {
let value,
i = 0,
length = obj.length,
isArray = isArraylike(obj)
if (isArray) { // 迭代類數(shù)組
for (; i < length; i++) {
value = callback.call(obj[i], i, obj[i])
if (value === false) {
break
}
}
} else {
for (i in obj) { // 迭代object 對象
value = callback.call(obj[i], i, obj[i])
if (value === false) {
break
}
}
}
return obj
}
??迭代器可以像普通for循環(huán)中的break一樣,提供一種跳出循環(huán)的方法。在jQuery的each函數(shù)里有這樣一句if(value===false){ break; }
參考文獻
《JavaScript設計模式與開發(fā)實踐》