迭代器工厂:生成器
阅读 1.6k
在上一篇《优雅的遍历:迭代器》中,已经知道了迭代器的用途,但没有说明如何获得迭代器,本篇就如何获得迭代器进行介绍。
什么是生成器
生成器就是一个返回迭代器
的函数,它长这样:
javascriptfunction* generator() { yield 3 yield 6 } let iterator = generator()
它和普通函数很像,但也带有明显的个人特色,第一个特色是function关键字后面带有星号(*)
,第二个特色是函数体中有关键字yield
。通过调用它就会获得一个迭代器。
对于生成器而言,其最特殊的地方在于每执行一条yield语句后,函数就会自动停止执行
。
比如,上面代码中,执行完语句yield 3
之后,函数便不再执行其他语句,直到再次调用迭代器的next()方法才会继续执行yield 6
语句。
默认的迭代器
在上一篇中,我们遇到了一个疑惑:就是用for-of
迭代数组时,JavaScript引擎
到底帮我们做了什么?其实是这样:
javascriptlet arr = [100, 200, 300] let iterator = arr[Symbol.iterator]()
通过Symbol.iterator
获取了数组arr的默认迭代器。由于具有Symbol.iterator属性的对象都有默认的迭代器,因此可以用它来检测对象是否为可迭代对象:
javascriptfunction isIterable(object) { return typeof object[Symbol.iterator] === "function" }
上面的isIterable()
函数可以检测指定对象中是否存在默认的迭代器,for-of在执行前也会做类似的检查。
创建可迭代对象
默认情况下,开发者创建的对象都是不可迭代对象,如果要将其变成可迭代的对象,需要给它添加一个Symbol.iterator
属性,并且该属性是一个生成器:
javascriptlet collection = { items: [], *[Symbol.iterator]() { for (let item of this.items) { yield item } } } collection.items.push(100) collection.items.push('abc') for (let col of collection) { console.log(col) }
上面代码中,给collection对象添加了一个Symbol.iterator属性(生成器),这样,collection就从不可迭代变成了可迭代。
参考
- 深入理解ES6,Nicholas C. Zakas
最后编辑于: 2022-06-28