本文小編為大家詳細(xì)介紹“JavaScript迭代器知識點(diǎn)有哪些”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“JavaScript迭代器知識點(diǎn)有哪些”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
為耒陽等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及耒陽網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、耒陽網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
迭代就是指可以從一個(gè)數(shù)據(jù)集中按照一定的順序,不斷取出數(shù)據(jù)的過程。
那么迭代和遍歷有啥子區(qū)別呢?
迭代強(qiáng)調(diào)依次取數(shù)據(jù)的過程,不保證把所有的數(shù)據(jù)都取完
遍歷強(qiáng)調(diào)的是要把所有的數(shù)據(jù)依次全部取出
在JavaScript中,迭代器是能調(diào)用 next
方法實(shí)現(xiàn)迭代的一個(gè)對象,該方法返回一個(gè)具有兩個(gè)屬性的對象。
value
:可迭代對象的下一個(gè)值
done
:表示是否已經(jīng)取出所有的數(shù)據(jù)了。 false
表示還有數(shù)據(jù), true
表示后面已經(jīng)沒有數(shù)據(jù)了。
通過可迭代對象中的迭代器工廠函數(shù) Symbol.iterator
來生成迭代器。
const arr = []console.log(arr)
const arr = [1, 2, 3] const iter1 = arr[Symbol.iterator]() // 通過迭代器工廠函數(shù)` Symbol.iterator`來生成迭代器。 console.log(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log('%c%s', 'color:red;font-size:24px;', '================') const mymap = new Map() mymap.set('name', 'clz') mymap.set('age', 21) const iter2 = mymap[Symbol.iterator]() // 通過迭代器工廠函數(shù)` Symbol.iterator`來生成迭代器。 console.log(iter2) console.log(iter2.next()) console.log(iter2.next()) console.log(iter2.next())
可以發(fā)現(xiàn),迭代器是取完最后一個(gè)值之后,即迭代器下一個(gè)值 value
為 undefined
時(shí),完成。
但是,上面的說法并不是很準(zhǔn)確,并不是迭代器下一個(gè)值 value
為 undefined
時(shí),就完成的。還需要判斷是不是真的沒有值,還是是可迭代對象里就有一個(gè)值為 undefined
。如果是可迭代對象里有一個(gè)值為 undefined
的情況,那么此時(shí)還是不會變成完成狀態(tài)。
const arr = [1, 2, 3, undefined] const iter1 = arr[Symbol.iterator]() // 通過迭代器工廠函數(shù)` Symbol.iterator`來生成迭代器。 console.log(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next())
可以多次調(diào)用迭代器工廠函數(shù)來生成多個(gè)迭代器,每個(gè)迭代器都表示對可迭代對象的一次性有序遍歷。不同迭代器之間互不干擾,只會獨(dú)立地遍歷可迭代對象。
const arr = [1, 2, 3] const iter1 = arr[Symbol.iterator]() // 通過迭代器工廠函數(shù)` Symbol.iterator`來生成迭代器。 const iter2 = arr[Symbol.iterator]() console.log('迭代器1:', iter1.next()) console.log('迭代器2:', iter2.next()) console.log('迭代器1:', iter1.next()) console.log('迭代器2:', iter2.next())
const arr = [1, 2, 3] const iter = arr[Symbol.iterator]() for (const i of iter) { console.log(i) // 依次輸出1、2、3 }
如果可迭代對象在迭代期間被修改了,迭代器得到的結(jié)果也會是修改后的。
const arr = [1, 2, 3] console.log(arr) const iter = arr[Symbol.iterator]() console.log(iter.next()) arr[1] = 999 console.log(iter.next()) console.log(iter.next())
當(dāng)我們迭代到 done: true
之后,再調(diào)用next
是不是會報(bào)錯(cuò),或者不返回任何內(nèi)容呢?
然而,并不是,迭代器會處于一種完成但并不完成的狀態(tài), done: true
表示已經(jīng)完成了,但是后續(xù)還能一直調(diào)用 next
,雖然得到的結(jié)果一直都會是 { value: undefined, done: true }
。這就是為什么說完成但并不完成。
const arr = [1, 2, 3] const iter = arr[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())
從上面的例子中,我們就可以知道是通過通過迭代器工廠函數(shù) Symbol.iterator
來生成迭代器,所以我們需要實(shí)現(xiàn)一個(gè)迭代器迭代器工廠函數(shù),然后迭代器可以調(diào)用 next
方法,所以還需要實(shí)現(xiàn)一個(gè) next
方法,至于迭代器工廠函數(shù),實(shí)際上直接返回實(shí)例 this
。
計(jì)數(shù)器例子:
class Counter { constructor(limit) { this.count = 1 this.limit = limit } next() { if (this.count <= this.limit) { return { done: false, value: this.count++ } } else { return { done: true, value: undefined } } } [Symbol.iterator]() { return this }}
const counter = new Counter(3) const iter = counter[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())
乍一看,沒啥問題,但是如果我們使用 for-of
來遍歷就能發(fā)現(xiàn)問題。
const counter = new Counter(3)for (let i of counter) { console.log(i)}console.log('另一輪迭代:')for (let i of counter) { console.log(i)}
使用 for-of
循環(huán)也變成一次性的了。這是因?yàn)?code> count是該實(shí)例的變量,所以兩次迭代都是使用的那一個(gè)變量,但是該變量第一次循環(huán)完之后,就已經(jīng)超過限制了,所以再次使用 for-of
循環(huán)就得不到任何的結(jié)果了。
可以把 count
變量放在閉包里,然后通過閉包返回迭代器,這樣子每創(chuàng)建一個(gè)迭代器都會對應(yīng)一個(gè)新的計(jì)數(shù)器。
class Counter { constructor(limit) { this.limit = limit } [Symbol.iterator]() { let count = 1 const limit = this.limit return { // 迭代器工廠函數(shù)必須要要返回一個(gè)帶有next方法的對象,因?yàn)榈鷮?shí)際就是通過調(diào)用next方法來實(shí)現(xiàn)的 next() { if (count <= limit) { return { done: false, value: count++ } } else { return { done: true, value: undefined } } } } }}
測試
const counter = new Counter(3)for (let i of counter) { console.log(i)}console.log('另一輪迭代:')for (let i of counter) { console.log(i)}
就和使用 for-of
循環(huán)一樣,迭代器會很聰明地去調(diào)用 next
方法,當(dāng)?shù)魈崆敖K止時(shí),它也會去調(diào)用 return
方法。
[Symbol.iterator]() { let count = 1 const limit = this.limit return { // 迭代器工廠函數(shù)必須要要返回一個(gè)帶有next方法的對象,因?yàn)榈鷮?shí)際就是通過調(diào)用next方法來實(shí)現(xiàn)的 next() { if (count <= limit) { return { done: false, value: count++ } } else { return { done: true, value: undefined } } }, return() { console.log('提前終止迭代器') return { done: true } } }}
測試
const counter = new Counter(5)for (let i of counter) { if (i === 3) { break; } console.log(i)}
如果迭代器沒有關(guān)閉,就可以繼續(xù)從上次離開的地方繼續(xù)迭代。數(shù)組地迭代器就是不能關(guān)閉的。
const arr = [1, 2, 3, 4, 5]const iter = arr[Symbol.iterator]()iter.return = function () { console.log('提前退出迭代器') return { done: true }}for (const i of iter) { console.log(i) if (i === 2) { break }}for (const i of iter) { console.log(i)}
讀到這里,這篇“JavaScript迭代器知識點(diǎn)有哪些”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。