知识点
- Iterator接口
- Generatorr函数
题目
完成一个类Box
,实例化的时候给它传入一个数组。Box
的实例支持for...of
操作,可以把初始化的时候传给Box
的数组内容遍历出来:
const box = new Box(['book', 'money', 'toy'])
for (let stuff of box) {
console.log(stuff) // => 依次打印 'book', 'money', 'toy'
}
不能在constructor
里面直接返回数组。
实现
使用Generator函数
要求能使用for...of
进行遍历,也就是说需要为Box
的实例对象添加一个遍历器接口,也就是Iterator接口,部署了这个接口后,就可以完成遍历操作
数据的Iterator接口部署在数据接口的Symbol.iterator
属性上,Symbol.iterator
的值就是一个Symbol值Symbol(Symbol.iterator)
所以我们要在实例的Symbol.iterator
属性上定义一个函数,它应该是一个Iterator对象,我们这里定义的函数是一个Generator函数,它的返回值就是一个Iterator对象,它默认提供了next
方法供便利时调用
所以:
class Box {
constructor(arr) {
this[Symbol.iterator] = function* () {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
}
}
不使用Generator函数
我们之所以能够使用上面的Generator函数,就是因为它的返回结果是一个Iterator对象,这个Iterator对象有next
方法,每次遍历时都要调用这个方法,返回的记结果就是包含了value
和done
两个属性的值
所以,我们不使用Generator函数,自己都构造返回一个具有next
方法的对象也是可以的,next
方法返回对象也需要包括了value
和done
连个属性,value
属性是for...of
的返回值,done
用来标识遍历何时结束。
class Box {
constructor(arr) {
this[Symbol.iterator] = function* () {
let index = 0;
return {
next() {
return { value: arr[index], done: index === arr.length }
}
}
}
}
}