一、Iterator:迭代器
迭代器是一種特殊對(duì)象,它具有一些專門為迭代過程設(shè)計(jì)的專有接口,所有的迭代器對(duì)象都有一個(gè)next()
方法捣郊,每次調(diào)用都返回一個(gè)結(jié)果對(duì)象。結(jié)果對(duì)象有兩個(gè)屬性:一個(gè)是value
慈参,表示下一個(gè)將要返回的值呛牲;另一個(gè)是done
,它是一個(gè)布爾類型的值驮配,當(dāng)沒有更多可返回?cái)?shù)據(jù)時(shí)返回true
娘扩。迭代器還會(huì)保存一個(gè)內(nèi)部指針着茸,用來指向當(dāng)前集合中值的位置,每調(diào)用一次next()
方法琐旁,都會(huì)返回下一個(gè)可用的值涮阔。
具有 Iterator 接口的數(shù)據(jù)結(jié)構(gòu):
- Array / 類數(shù)組
- String
- Set 集合
- Map 集合
Iterator 迭代器的原理:
默認(rèn)的 Iterator 接口部署在數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator
屬性,一個(gè)數(shù)據(jù)結(jié)構(gòu)只要具有 Symbol.iterator
屬性灰殴,就是可迭代的敬特。
二、Generator:生成器
生成器是一種返回迭代器的函數(shù)牺陶,通過function關(guān)鍵字后的星號(hào)(*)來表示擅羞,函數(shù)中會(huì)用到新的關(guān)鍵字yield
。yield
關(guān)鍵字也是ES6的新特性义图,可以通過它來指定調(diào)用迭代器的next()
方法時(shí)的返回值及返回順序
function* createIterator(array) {
for (let i = 0; i < array.length; i++) {
yield array[i]
}
}
let iterator = createIterator([1, 2, 3])
console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: undefined, done: true }
生成器函數(shù)的一個(gè)特點(diǎn)是,當(dāng)執(zhí)行完一句 yield
語句后函數(shù)會(huì)自動(dòng)停止執(zhí)行召烂,再次調(diào)用迭代器的 next()
方法才會(huì)繼續(xù)執(zhí)行下一個(gè) yield
語句碱工。
async/await
語法糖便是采用了這種方法。
yield
關(guān)鍵字只可在生成器內(nèi)部使用奏夫,在其他地方使用會(huì)報(bào)錯(cuò)怕篷;
不能用箭頭函數(shù)來創(chuàng)建生成器。
三酗昼、可迭代對(duì)象和 for-of 循環(huán)
for-of
用來循環(huán)遍歷可迭代對(duì)象廊谓,for-of
循環(huán)內(nèi)部調(diào)用的就是數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator
方法。
const array = [1, 2, 3]
for (const item of array) {
console.log(item)
}
// 1
// 2
// 3
對(duì)于使用for-of
的可迭代對(duì)象麻削,for-of
每執(zhí)行一次就會(huì)調(diào)用這個(gè)可迭代對(duì)象的 next()
蒸痹,并將返回結(jié)果存儲(chǔ)在一個(gè)變量中,持續(xù)執(zhí)行直到可迭代對(duì)象 done
屬性值為 false
呛哟。
非迭代對(duì)象使用 for of
循環(huán)需要對(duì)其添加 Symbol.iterator
屬性:
const obj = {a: 1, b: 2, c: 3}
obj[Symbol.iterator] = function () {
let i = 0
const keys = Object.keys(this)
return {
next: () => {
return i <= keys.length - 1 ?
{value: this[keys[i++]], done: false} :
{value: undefined, done: true}
}
}
}
for (let item of obj) {
console.log(item)
}
// 1
// 2
// 3