es6的Interator
Last Updated:2022-08-12
遍历器常常给for...of
循环和while
循环用,当然,还有别的场合
- 解构赋值对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法。
- 扩展运算符扩展运算符(...)也会调用默认的 Iterator 接口。
实际上,这提供了一种简便机制,可以将任何部署了 Iterator 接口的数据结构,转为数组。也就是说,只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符,将其转为数组。
let arr = [...iterable];
yield*
yield*
后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
- 其他场合 由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。下面是一些例子。
- for...of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如
new Map([['a',1],['b',2]])
) - Promise.all()
- Promise.race()
默认部署在Symbol.interator
属性上
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是 “可遍历的”(iterable)。Symbol.iterator
属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator
,它是一个表达式,返回Symbol
对象的iterator
属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内(参见《Symbol》一章)。
要获得遍历器对象,需要调用上述的Symbol.interator
属性(是个函数)
例如: let iter = arr[Symbol.iterator]();
原生具备 Iterator 接口的数据结构列表
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
一个对象如果要具备可被for...of
循环调用的 Iterator 接口,就必须在Symbol.iterator
的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
对于类似数组的对象(存在数值键名和length属性),部署 Iterator 接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的 Iterator 接口。
NodeList 对象是类似数组的对象,本来就具有遍历接口,可以直接遍历。上面代码中,我们将它的遍历接口改成数组的Symbol.iterator属性,可以看到没有任何影响。下面是另一个类似数组的对象调用数组的Symbol.iterator方法的例子。 例2: ^f27c59
Iterator 接口与 Generator 函数
Symbol.iterator()
方法的最简单实现,还是使用下一章要介绍的 Generator 函数。
遍历器对象的 return(),throw()
遍历器对象除了具有next()
方法,还可以具有return()
方法和throw()
方法。如果你自己写遍历器对象生成函数,那么next()
方法是必须部署的,return()
方法和throw()
方法是否部署是可选的。
return()
方法的使用场合是,如果for...of
循环提前退出(通常是因为出错,或者有break
语句),就会调用return()
方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return()
方法。
^230510
上面代码中,函数readLinesSync
接受一个文件对象作为参数,返回一个遍历器对象,其中除了next()
方法,还部署了return()
方法。下面的两种情况,都会触发执行return()
方法。
上面代码中,情况一输出文件的第一行以后,就会执行return()
方法,关闭这个文件;情况二会在执行return()
方法关闭文件之后,再抛出错误。
注意,return()
方法必须返回一个对象,这是 Generator 语法决定的。
throw()
方法主要是配合 Generator 函数使用,一般的遍历器对象用不到这个方法。请参阅《Generator 函数》一章。