一、用生成器给对象定义迭代器
常规方法
const obj = { a: 1, b: 2, c: 3, [Symbol.iterator]() { let [index, values] = [0, Object.values(this)] return { next() { const done = (index >= values.length) const value = done ? undefined : values[index++] return { done, value } } } } } for (let v of obj) { console.log(v) // 1 2 3 }
使用生成器
const obj = { a: 1, b: 2, c: 3, *[Symbol.iterator]() { let [index, values] = [0, Object.values(this)] for (let v of values) { yield v } } } for (let v of obj) { console.log(v) // 1 2 3 }
生成器(*
)实际上是一种返回迭代器的函数。
二、访问默认迭代器
访问数组的默认迭代器
const arr = [1, 2, 3] const arrIterator = arr[Symbol.iterator]() console.log(arrIterator.next()) // {value: 1, done: false} console.log(arrIterator.next()) // {value: 2, done: false} console.log(arrIterator.next()) // {value: 3, done: false} console.log(arrIterator.next()) // {value: undefined, done: true}
在引擎中 for-of
循环也是执行了以上类似的处理过程。
三、迭代器和扩展运算符
通过扩展运算符(...
)将拥有迭代器的对象转换成一个数组。
const obj = { a: 1, b: 2, c: 3, *[Symbol.iterator]() { let [index, values] = [0, Object.values(this)] for (let v of values) { yield v } } } console.log([...obj]) // [1, 2, 3]
四、迭代器和字符串
yield *
可以用于字符串,换言之,就是可以用于拥有迭代器的对象/包装对象。
const strIterator = (function *() { yield * 'Hello' })() console.log([...strIterator]) // ['H', 'e', 'l', 'l', 'e']