迭代器、生成器

简介: 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
}
目录
相关文章
|
存储 JSON 数据格式
JSON - JSONObject 按 Put 顺序输入和输出
JSON - JSONObject 按 Put 顺序输入和输出
1137 0
JSON - JSONObject 按 Put 顺序输入和输出
|
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编译器有关。
5196 0
GDAL创建JPG或PNG格式图像
GDAL创建JPG或PNG格式图像
215 0
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
572 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
安全 Unix Linux
好工具推荐系列:开源的杀毒软件
好工具推荐系列:开源的杀毒软件
2168 0
|
存储 编解码 数据挖掘
VOD(Video on Demand)
VOD(Video on Demand)是指视频点播,是一种通过互联网或其他数字传输网络,在用户需求下,按照用户选择的节目或者内容,随时、任意、快速地进行点播的服务。通俗地说,就是用户可以随时随地通过网络观看自己选择的视频内容,而不需要等待节目的播出时间。
1061 1
关闭阿里云的短信提醒
阿里云方便是方便,但是有太多的短信骚扰,所以可以考虑关闭一些阿里云的短信提醒 找到消息中心  如何联系我:【万里虎】www.bravetiger.cn 【QQ】3396726884 (咨询问题100元起,帮助解决问题500元起) 【博客】http://www.
2776 0
|
机器学习/深度学习 人工智能 达摩院
魔搭语音更新|七大模型最新开源,推理速度升级,几行代码可实现微调
自ModelScope魔搭社区发布以来,众开发者在ModelScope上传与下载模型,并集成到自己的语音识别服务中。为了方便用户更好地利用ModelScope进行语音识别服务,我们推出了语音识别基础框架FunASR,希望在语音识别的学术研究和工业应用之间架起一座桥梁。FunASR已经集成到ModelScope中,提供的工业级的语音识别模型的推理与微调定制,使得研究人员和开发者可以更加便捷的进行语音识别模型的研究和生产,促进语音识别生态的发展。
1145 0
|
存储 搜索推荐 Go
跟着动画学 Go 数据结构之堆排序
堆排序是一种树形选择排序算法。简单选择排序算法每次选择一个关键字最小的记录需要 O(n) 的时间,而堆排序选择一个关键字最小的记录需要 O(nlogn) 的时间。
跟着动画学 Go 数据结构之堆排序
|
Java
启动SpringBoot项目,报错:无法配置数据源:未指定“url”属性,并且无法配置嵌入式数据源。求解求解
启动SpringBoot项目,报错:无法配置数据源:未指定“url”属性,并且无法配置嵌入式数据源。求解求解
621 0
启动SpringBoot项目,报错:无法配置数据源:未指定“url”属性,并且无法配置嵌入式数据源。求解求解