Unique's Blog

迭代器和生成器

2022-11-23 · 1020字 · 4 min read
🏷️  JavaScript

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 可省略;

注意:

  1. 不能判断一个特定的对象是否实现了迭代器协议

  2. 创建同时满足迭代器协议和可迭代协议是容易的,例如 Map 的 keys()/values()/entries() 方法返回的对象.

因此,迭代器一般都会实现可迭代协议成为可迭代对象

var myIterator = {
  next: function () {
    // ...
  },
  [Symbol.iterator]: function () {
    return this
  }
}

内置可迭代对象

StringArrayTypedArrayMap和  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

本文已被阅读 0 次,该数据仅供参考

欢迎任何与文章内容相关并保持尊重的评论😊 !

共 43 篇文章 | Powered by Gridea | RSS
©2020-2024 Nuo. All rights reserved.