JavaScript高级程序设计4 第七章 迭代器与生成器
理解迭代
循环是迭代机制的基础,这是因为他可以指定迭代的次数,以及每次迭代要执行什么操作。每次循环都会在下一次迭代开始之前完成,而每次迭代的顺序都是事先定义好的。
迭代会在一个有序集合上进行。
迭代器模式
迭代器模式:即可以吧有些结构成为“可迭代对象”,因为它们实现了正式的Iterable接口,而且可以通过迭代器Iterator消费
可迭代协议
实现Iterable接口(可迭代协议)要求同时具备两种能力:支持迭代的自我识别能力和创建实现Iterator接口的对象的能力。
迭代器协议
迭代器是一种一次性使用的对象,用于迭代与其关联的可迭代对象。迭代器API使用next()方法在可迭代对象中遍历数据。如果每次调用成功,都会返回一个IteratorResult对象,其中包含迭代器返回的下一个值。
每个迭代器都表示对可迭代对象的一次性有序遍历。不同迭代器的实例相互之间没有联系,只会独立地遍历可迭代对象。
迭代器维护着一个指向可迭代对象的引用,因此迭代器会组织垃圾回收程序回收可迭代对象、
自定义迭代器
与Iterable接口类似,任何实现Iterator接口的对象都可以作为迭代器使用。
提前终止迭代器
可选的return()方法用于指定在迭代器提前关闭时执行的逻辑。
如果迭代器没有关闭,则还可以继续从上次离开的地方继续迭代
并非所有的迭代器都是可关闭的。要知道某个迭代器是否可关闭,可以测试这个迭代器实例的return属性是不是函数对象。
生成器
生成器是一个极为灵活的结构,拥有在一个函数块内暂停和恢复代码执行的能力。
生成器基础
生成器的形式是一个函数,函数名称前面加一个星号(*)表示它是一个生成器。只要是可以定义函数的地方,就可以定义生成器。
箭头函数不能用来定义生成器函数。
调用生成器函数会产生一个生成器对象。生成器对象一开始处于暂停执行的状态。与迭代器相似,生成器也实现了Iterator接口,因此具有next()方法。调用这个方法会让生成器开始或恢复执行。
yield中断执行
yield关键字可以让生成器停止执行。
通过yield关键字退出的生成器会处在done:false状态,通过return关键字退出的生成器函数会处于done:true状态。
生成器函数内部的执行流程会针对每个生成器对象区分作用域。在一个生成器对象上调用next()不会影响其他生成器。
yield关键字只能在生成器函数内部使用,用在其他地方会抛出错误。
yield关键字还可以作为函数的中间参数使用。上一次让生成器函数暂停的yield关键字会接收到传给next()方法的第一个值。第一次调用next()传入的值不会被使用,因为这一次调用是为了开始执行生成器函数。
使用星号增强yield的行为,让他能够迭代一个可迭代对象。yield*实际上只是将一个可迭代对象序列化成一连串可以单独产出的值,所以这跟吧yield放到一个循环里没有区别。
yield*的值是关联迭代器返回done:true时的value属性。
提前终止生成器
return()和throw()方法都可以用于强制生成器进入关闭状态
return()方法会强制生成器进入关闭状态。提供给return()方法的值,就是终止迭代器对象的值。只有通过它进入关闭状态,就无法恢复了。后续调用next()会显示done:true状态,而提供的任何返回值都不会被存储或传播。
throw()方法会在暂停的时候将一个提供的错误注入到生成器对象中。如果错误未处理生成器就会关闭,如果生成器内部处理了这个错误,那么生成器就不会关闭,而且还可以恢复执行。错误处理会跳过对应的yield