迭代器、生成器

简介: JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来了解JavaScript中的迭代器、生成器

迭代器

迭代器是一个对象,让我们能够遍历某个数据结构(如:链表或数组)
在JS中,迭代器是一个对象且还需要有next函数(符合迭代器协议)
const iterator = {next: function() {return {}}}

next函数

一个 无参数函数,返回一个应当拥有done和value属性的对象:

done (boolean):

  • 如果迭代器可以产生序列中的下一个值,则为 false。(这等价于没有指定 done 这个属性。)
  • 如果迭代器已将序列迭代完毕,则为 true。这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值。

value:迭代器返回的任何 JavaScript 值。done 为 true 时可省略。

// 数组
const names = ["abc", "cba", "nba"]

// 创建一个迭代器对象来访问数组
let index = 0
const namesIterator = {
  next: function() {
    if (index < names.length) {
      return { done: false, value: names[index++] }
    } else {
      return { done: true, value: undefined }
    }
  }
}

console.log(namesIterator.next())
console.log(namesIterator.next())

可迭代对象

可迭代对象是一个对象且需要实现 @@iterator方法,我们可以使用Symbol.iterator访问该属性(符合可迭代协议)
const iterableObj = {[Symbol.iterator]: function(){return 迭代器}}
const iterableObj = {
  names: ["abc", "cba", "nba"],
  [Symbol.iterator]: function() {
    let index = 0
    return {
      next: () => {  // 使用箭头函数使this指向iterableObj
        if (index < this.names.length) {
          return { done: false, value: this.names[index++] }
        } else {
          return { done: true, value: undefined }
        }
      }
    }
  }
}

用于可迭代对象的语法:

  1. for ...of 可以遍历的东西必须是一个可迭代对象
  2. 展开运算符 (...) [ 在ES9之后新增的特性:普通对象也可以使用展开运算符 ]
  3. 解构赋值 [ 在ES9之后新增的特性:普通对象也可以使用解构赋值]
  4. yield*
  5. 使用Set 、Array.from 创建对象时需要传入可迭代对象

内置可迭代对象

String、Array、TypedArray、Map 和 Set 都是内置可迭代对象,因为它们的原型对象都拥有一个 Symbol.iterator 方法

// 以数组为例:
const names = ["abc", "cba", "nba"]
console.log(names[Symbol.iterator])

生成器

与函数相关,是ES6新增的一种函数控制、使用的方案(控制函数什么时候继续执行、暂停执行等操作)
生成器函数返回值是一个生成器

生成器函数

生成器函数特点:

  • 生成器函数需要在function的后面加一个符号:*
  • 生成器函数可以通过yield关键字来控制函数的执行流程
  • 生成器函数的返回值是一个Generator(生成器)
function* foo() {
  console.log("函数开始执行~")

  const value1 = 100
  console.log("第一段代码:", value1)
  yield

  const value2 = 200
  console.log("第二段代码:", value2)
  yield

  console.log("函数执行结束~")
}

// 调用生成器函数时, 会给我们返回一个生成器对象
const generator = foo()

// 开始执行第一段代码
generator.next()

我们使用第一个next()调用的时候,执行的是第一个yield上面的代码

  • 当遇到yield时候值暂停函数的执行
  • 当遇到return时候生成器就停止执行
  • 如果想要第一个next返回的结果不是undefined,则在yield之后加上想要返回的值:yield value1

生成器本质上是一个特殊的迭代器

//打印的结果与迭代器的形式是一样的
const generator = foo()
console.log("返回值:", generator.next())
// 返回值: { value: undefined, done: false }

生成器的方法使用

next传递参数

我们在调用next函数的时候,可以给它传递参数,那么这个参数会作为上一个yield语句的返回值;而这个传递进来的参数则为下一个代码块执行提供了一个值
function* foo(num) {
  console.log("函数开始执行~")

  const value1 = 100 * num
  console.log("第一段代码:", value1)
  const n = yield value1

  const value2 = 200 * n
  console.log("第二段代码:", value2)

  console.log("函数执行结束~")
  return "123"
}

// 生成器上的next方法可以传递参数
//给第一个代码块传参
const generator = foo(5)  // 传入的5被上面的num接收
generator.next()
// 给第二个代码块传参,传入的10对应上面的n
generator.next(10)

return终止执行

// 相当于在代码块的后面加上return, 就会提前终端生成器函数代码继续执行
generator.return(15)

用生成器替代迭代器

// 原先用迭代器实现:
function createArrayIterator(arr) {
  let index = 0
  return {
    next: () => {  
      if (index < arr.length) {
         return { done: false, value: arr[index++] }
      } else {
        return { done: true, value: undefined }
      }
    }
  }
}
因为生成器是特殊的迭代器,所以我们可以用生成器去简化代码:
function* createArrayIterator(arr) {
  for (const item of arr) {
    yield item
  }
}

yield*

yield*是一种yield的语法糖,可以用它来生产一个可迭代对象
如下面的 yield* arr ,这个代码会依次迭代 arr 这个可迭代对象,每次迭代其中的一个值
function* createArrayIterator(arr) {
  yield* arr
}
目录
相关文章
|
C语言 机器学习/深度学习 C++
C语言的几种取整方法
C语言的几种取整方法 来源:http://blog.sina.com.cn/s/blog_4c0cb1c001013ha9.html 1、直接赋值给整数变量。如: int i = 2.5; 或 i = (int) 2.5; 这种方法采用的是舍去小数部分 2、C/C++中的整数除法运算符“/”本身就有取整功能(int / int),但是整数除法对负数的取整结果和使用的C编译器有关。
5544 0
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
764 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
机器学习/深度学习 人工智能 算法
介绍一下AI在药物研发中的应用。
【10月更文挑战第16天】介绍一下AI在药物研发中的应用。
624 0
|
机器学习/深度学习 人工智能 自然语言处理
NVIDIA Triton系列03-开发资源说明
NVIDIA Triton 推理服务器是用于高效部署机器学习模型的开源工具。本文介绍了初学者如何通过官方文档和 GitHub 开源仓库获取开发资源,包括快速启动指南、生产文档、示例和反馈渠道。特别强调了核心仓库中的六个重要部分,涵盖服务器部署、核心功能、后端支持、客户端接口、模型分析和模型导航工具。这些资源有助于初学者全面了解和掌握 Triton 项目。
442 0
NVIDIA Triton系列03-开发资源说明
|
开发工具 Android开发 iOS开发
安卓与iOS开发环境深度对比
【10月更文挑战第1天】本文旨在探讨和分析安卓(Android)与苹果(iOS)两大主流移动操作系统在应用开发环境上的不同点。通过比较它们的开发工具、语言、用户体验设计、市场策略及生态系统,本文将为开发者提供一份详尽的参考指南,帮助他们做出更合适的开发平台选择。此外,文章还将探讨两大平台未来的发展趋势,以及这些趋势可能对开发者和用户产生的影响。
295 1
|
Unix C语言
UNIX操作系统的开发始于1969年
UNIX操作系统的开发始于1969年
413 5
|
Linux 开发工具 Python
【Deepin 20系统】Linux系统从零打造完美VScode for Python环境
如何在Deepin 20系统中从零开始配置一个完美的VScode for Python开发环境,包括安装Anaconda、VScode、必要的插件、汉化、主题和字体设置,以及如何运行和调试Python程序。
523 6
|
JavaScript 前端开发 开发者
浏览器事件机制详解
浏览器事件机制详解
331 1
|
运维 安全 网络安全
怎样用CDN防篡改、抗攻击、控内容?一份CDN安全指南请查收
阿里云CDN经过10多年的技术沉淀和实践,已经从传统的加速,逐渐构筑起一个边缘+云的安全网络立体防护体系,从全链路安全传输、常见攻击类型的边缘防御、企业级独享资源部署、运维以及内容安全保障机制几个维度,为企业通向网络提供安全可靠的桥梁。
2912 0
怎样用CDN防篡改、抗攻击、控内容?一份CDN安全指南请查收