https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols
可迭代对象:对象必须实现 @@iterator
方法,这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator
的属性,可通过常量 Symbol.iterator
访问该属性。可迭代对象可以使用 for…of 中遍历,使用展开语法 …object
,解构赋值等
[Symbol.iterator]
一个无参函数,返回一个迭代器对象
此函数可以是普通函数,也可以是生成器函数
一个对象需要被迭代,首先调用它的 @@iterator
方法,然后使用此方法返回的迭代器获得要迭代的值
迭代器协议定义了产生一系列值的标准方式。
定义了特定语义的 next()
方法,该对象才能成为迭代器:
{done: boolean, value: any}
,done
为 true 时属性 value
可省略;注意:
不能判断一个特定的对象是否实现了迭代器协议
创建同时满足迭代器协议和可迭代协议是容易的,例如 Map 的 keys()/values()/entries()
方法返回的对象.
因此,迭代器一般都会实现可迭代协议成为可迭代对象:
var myIterator = {
next: function () {
// ...
},
[Symbol.iterator]: function () {
return this
}
}
String
、Array
、TypedArray
、Map
和 Set
,它们的原型对象都实现了 @@iterator
方法。
例如,简单的 map 示例:(只是为了说明迭代原理,非底层实现)
生成器对象是由一个 generator function 返回的,它是迭代器(next 方法),也是可迭代对象(@@iterator
)。
function*
声明方式,定义一个生成器函数,其返回一个生成器对象。
执行流程:
next()
方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield
的位置为止,yield
后紧跟迭代器要返回的值。
或者如果用的是 yield*
(多了个星号),则表示将执行权移交给另一个生成器函数;
next()
方法返回一个对象,这个对象包含两个属性:value 和 done(迭代器语义)
调用 next()
方法时,如果传入了参数,那么这个参数会传给上一条执行的 yield 语句左边的变量
注意:生成器函数中 return 可以提前结束生成器的状态(next 返回的对象 done:true),可以返回值。返回的生成器对象也可以调用 return 函数提前结束。
let aGeneratorObject = (function* () {
yield 1
yield 2
yield 3
})() // 返回生成器对象
typeof aGeneratorObject.next // 返回"function", 因为有一个 next 方法,所以这是一个迭代器
typeof aGeneratorObject[Symbol.iterator] // 返回"function", 因为有一个 @@iterator 方法,所以这是一个可迭代对象
aGeneratorObject[Symbol.iterator]() === aGeneratorObject // true,因为 @@iterator 方法返回自身(即迭代器)
;[...aGeneratorObject] // 返回 [1, 2, 3]
console.log(Symbol.iterator in aGeneratorObject) // true
异步可迭代对象:定义了 Symbol.asyncIterator
属性,可用于 for await...of
循环。
(Symbol.asyncIterator
是一个用于访问对象的@@asyncIterator
方法的内建符号)
主要作用:迭代返回值的操作是异步操作时,优化性能。
使用for await...of
语句创建一个循环,可遍历异步可迭代对象,注意它也可以遍历上面的同步可迭代对象(相当于使用 Promise.resolve(val)包装). 同时存在,优先迭代返回的异步迭代器对象。
自定义异步可迭代对象
const myAsyncIterable = new Object()
myAsyncIterable[Symbol.asyncIterator] = async function* () {
yield 'hello'
yield 'async'
yield 'iteration!'
}
;(async () => {
for await (const x of myAsyncIterable) {
console.log(x)
// expected output:
// "hello"
// "async"
// "iteration!"
}
})()
异步迭代器,可以看作每次迭代返回的是一个 promise 对象。
注意:async 函数调用,await 后面的表达式执行都是同步操作,只有 await 语句后面的语句即回调才是异步执行(微任务)
本文链接: 迭代器和生成器
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
发布日期: 2022-11-23
最新构建: 2024-12-26
欢迎任何与文章内容相关并保持尊重的评论😊 !