一、Iterator:迭代器
迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值。
具有 Iterator 接口的数据结构:
- Array / 类数组
- String
- Set 集合
- Map 集合
Iterator 迭代器的原理:
默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,一个数据结构只要具有 Symbol.iterator 属性,就是可迭代的。
二、Generator:生成器
生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield。yield关键字也是ES6的新特性,可以通过它来指定调用迭代器的next()方法时的返回值及返回顺序
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 }
生成器函数的一个特点是,当执行完一句 yield 语句后函数会自动停止执行,再次调用迭代器的 next() 方法才会继续执行下一个 yield 语句。
async/await 语法糖便是采用了这种方法。
yield关键字只可在生成器内部使用,在其他地方使用会报错;
不能用箭头函数来创建生成器。
三、可迭代对象和 for-of 循环
for-of用来循环遍历可迭代对象,for-of循环內部调用的就是数据结构的Symbol.iterator方法。
const array = [1, 2, 3]
for (const item of array) {
console.log(item)
}
// 1
// 2
// 3
对于使用for-of的可迭代对象,for-of每执行一次就会调用这个可迭代对象的 next(),并将返回结果存储在一个变量中,持续执行直到可迭代对象 done 属性值为 false。
非迭代对象使用 for of 循环需要对其添加 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