JavaScript高级(十六)---Iterator迭代器/Generator生成器

 什么是迭代器?

迭代器是一种特殊的对象,这个对象需要符合迭代协议(iterator protocol),这个对象具有以下特点。

  • 该对象有一个特定的next方法

    const obj = {
        next() {
        }
    }  
 

    const obj = {
        next() {
            return { done:(boolean) , value:...}
        }
    }
 

例如:创建一个迭代器对象来访问数组

  • next方法形参是一个无参数或者有一个参数的函数,返回一个应当拥有以下两个属性的对象

  • done(boolean)
    • 如果迭代器可以产生序列中的下一个值,则为 false。
    • 如果迭代器已将序列迭代完毕,则为 true。这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值。
  • value
    • 迭代器返回的任何 JavaScript 值。done 为 true 时可省略。
    const arr = ["a", "b", "c", "d", "e", "f"]let index = 0;const iteratorArr = {next() {if (index < arr.length) {return { done: false, value: arr[index++] }} else {return { done: true, value: undefined }}}}console.log(iteratorArr.next())console.log(iteratorArr.next())console.log(iteratorArr.next())console.log(iteratorArr.next())console.log(iteratorArr.next())console.log(iteratorArr.next())console.log(iteratorArr.next())
可迭代对象

可迭代对象和迭代器是一个不同的概念,当一个对象实现了iterator protocol协议时,它就是一个可迭代对象,这个对象必须实现@@iterator方法,在代码中我们可以用[Symbol.iterator]来访问该属性。

当一个对象变成可迭代对象的时候,进行某些迭代操作,比如for..of,其实就是调用的它的@@iterator方法。

  • 可迭代对象代码
      const arrIterator = {arr: ["a", "b", "c", "d", "e", "f"],//实现iterator protocol协议 , 使用[Symbol.iterator]访问@@iterator[Symbol.iterator]() {let index = 0;//迭代器 一个特殊的对象return {// 特定的方法next()next: () => {// 返回一个对象 包含两个属性 done valueif (index < this.arr.length) {return { done: false, value: this.arr[index++] };} else {return { done: true, value: undefined }}}}}}const iterator = arrIterator[Symbol.iterator]();console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());
原生迭代器对象

事实上我们平时创建的很多原生对象已经实现了可迭代协议,会生成一个迭代器对象的,例如String,Array,Set,arguments,NodeList;

 // String 内部实现了可迭代协议var str = "Hello World";console.log(str[Symbol.iterator]())// for .. of 实际上都是在调用迭代器for (const item of str) {console.log(item)}// 展开运算符 实际上都是在调用迭代器console.log(...str)// Map,Setvar map = new Map();map.set('a', {})map.set('b', {})console.log(map[Symbol.iterator])// 展开运算符 实际上都是在调用迭代器console.log(...map)// argumentsfunction foo(x, y, z) {console.log(arguments[Symbol.iterator])// 展开运算符 实际上都是在调用迭代器console.log(...arguments)}foo(1, 2, 3)
可迭代对象的应用
  • JavaScript中语法:for ...of、展开语法(spread syntax)、yield*(后面讲)、解构赋值(Destructuring_assignment);
  • 创建一些对象时:new Map([Iterable])、new WeakMap([iterable])、new Set([iterable])、new WeakSet([iterable]);
  • 一些方法的调用:Promise.all(iterable)、Promise.race(iterable)、Array.from(iterable);
     // 展开运算符 const names = ["haha", "gaga", "heihei"]console.log(...names) //names内部有迭代协议// 对象内部没有可迭代协议 也不能进行for ofconst obj = {a: "1",b: "2",c: "3"}// ES9(ES2018)中新增的一个特性,用的不是迭代器console.log({ ...obj })// 解构语法const [haha, ...rest] = namesconsole.log(haha, rest)// ES9(ES2018)中新增的一个特性,用的不是迭代器const { a, ...args } = objconsole.log(a, args)
迭代器的中断

比如遍历的过程中通过break、continue、return、throw中断了循环操作;

    class classRoom {constructor(address, name, students) {this.address = address;this.name = name;this.students = students;}entry(student) {this.students.push(student);}[Symbol.iterator]() {let index = 0;return {next: () => {if (index < this.students.length) {return { done: false, value: this.students[index++] };} else {return { done: true, value: undefined };}},// 想要监听中断的话,可以添加return方法return() {return { done: true, value: undefined };}}}}const classroom = new classRoom("3幢5楼205", "计算机教室", ["james", "kobe", "curry", "why"])classroom.entry("lilei")for (const stu of classroom) {if (stu === 'kobe') break;console.log(stu)}

什么是生成器?

生成器是ES6中新增的一种函数控制、使用的方案,它可以让我们更加灵活的控制函数什么时候继续执行、暂停执行等。

平时我们会编写很多的函数,这些函数终止的条件通常是返回值或者发生了异常。

  • 生成器也是一个函数
    • 首先,生成器函数需要在function的后面加一个符号:*
    • 其次,生成器函数可以通过yield关键字来控制函数的执行流程:
    • 最后,生成器函数的返回值是一个Generator(生成器):
    • 生成器实际上是一个特殊的迭代器

生成器函数执行
      function* foo() {console.log("----start----")const value1 = 30console.log(value1)yieldconst value2 = 30console.log(value2)yieldconst value3 = 30console.log(value3)yieldconst value4 = 30console.log(value4)yieldconsole.log("----end----")return "ok"}// 这里不会调用函数,只是返回了一个遍历器对象,可以通过.next()调用const f = foo();console.log(f)f.next()f.next()f.next()f.next()f.next()f.next()
生成器传递参数
function* foo(num) {console.log("----start----")console.log(num)// x 不是yield的返回值,它是调用next() 回复当前 yield()执行传入的实参let x = yield '1'      //第一次执行 f.next() 会暂停在这里 . 第二次执行yield 如果传入了形参,就会赋值给xconsole.log('x' + x); let y = yield '2'console.log('y' + y)let z = yield '3'console.log('z' + z)console.log("----end----")return "ok"}// 这里不会调用函数,只是返回了一个遍历器对象,可以通过.next()调用const f = foo(5);f.next()   // 如果第一次就想传值  只能在foo() 这里面添加形参f.next(1)f.next(2)f.next(3)
生成器异步解决方案
// request.jsfunction requestData(url) {// 异步请求的代码会被放入到executor中return new Promise((resolve, reject) => {// 模拟网络请求setTimeout(() => {// 拿到请求的结果resolve(url)}, 2000);})}function* getData() {console.log('+++++')const res1 = yield requestData("第一次发送网络请求")const res2 = yield requestData("第二次发送网络请求" + res1)const res3 = yield requestData("第二次发送网络请求" + res2)console.log(res3 + '------')return 1}const generator = getData();// res1 res2 res3 都是形参generator.next().value.then(res => {console.log(res)generator.next('2').value.then(res => {console.log(res)generator.next('3').value.then(res => {console.log(res)generator.next('4').value.then(res => {console.log(res)})})})})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg-- c++实现:音频流aac和视频流h264封装

文章目录 流程api核心代码muxer.hmuxer.cpp aac 和 h264 封装为视频流&#xff0c;封装为c的Muxter类 流程 分配视频文件上下文 int Init(const char *url); 创建流&#xff0c;赋值给视频的音频流和视频流 int AddStream(AVCodecContext *codec_ctx); 写视频流的head int Se…

wayland(xdg_wm_base) + egl + opengles 使用 Assimp 加载带光照信息的材质文件Mtl 实现光照贴图的最简实例(十七)

文章目录 前言一、3d 立方体 model 属性相关文件1. cube1.obj2. cube1.Mtl3. 纹理图片 cordeBouee4.jpg二、实现光照贴图的效果1. 依赖库和头文件1.1 assimp1.2 stb_image.h2. egl_wayland_obj_cube1.cpp3. Matrix.h 和 Matrix.cpp4. xdg-shell-client-protocol.h 和 xdg-shell…

推免保研夏令营/预推免面试记录—北航网安

目录 0x00简述 0x01 面试经历 0x02 相关资料下载 0x00简述 没有夏令营,直接就是预推免,门槛基本等同于华五,或者说略弱于华五。招生规模较小,而且感觉导师方向一半是密码学,一半是那种类似于电信工的偏硬件方面。该校导师教授可以带两个学生,而副教授可以带一个。考…

小程序跨端组件库 Mpx-cube-ui 开源:助力高效业务开发与主题定制

Mpx-cube-ui 是一款基于 Mpx 小程序框架的移动端基础组件库&#xff0c;一份源码可以跨端输出所有小程序平台及 Web&#xff0c;同时具备良好的拓展能力和可定制化的能力来帮助你快速构建 Mpx 应用项目。 Mpx-cube-ui 提供了灵活配置的主题定制能力&#xff0c;在组件设计开发阶…

网络工程师练习题4

网络工程师 通过拨号远程配置Cisco路由器时&#xff0c;应使用的接口是&#xff08;&#xff09;。 A.AUXB.ConsoleC. EthernetD.VTY 【答案】A 【解析】使用AUX端口连接一台Modem&#xff0c;通过拨号远程配置路由器。 在Cisco路由器上配置RIPv1路由协议&#xff0c;参与…

【计算机视觉】Gaussian Splatting源码解读补充

本文旨在补充gwpscut创作的博文学习笔记之——3D Gaussian Splatting源码解读。 Gaussian Splatting Github地址&#xff1a;https://github.com/graphdeco-inria/gaussian-splatting 论文地址&#xff1a;https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/3d_gauss…

Minio的安装和Java使用示例

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Minio 是个基于 Go…

三段提交的理解

三阶段提交是在二阶段提交上的改进版本&#xff0c;3PC 最关键要解决的就是协调者和参与者同时挂掉的问题&#xff0c;所以3PC把2PC的准备阶段再次一分为二&#xff0c;这样三阶段提交。 处理流程如下 &#xff1a; 阶段一 协调者向所有参与者发出包含事务内容的 canCommit …

【MySQL】知识点 + 1

# &#xff08;1&#xff09;查询当前日期、当前时间以及到2022年1月1日还有多少天&#xff0c;然后通过mysql命令执行命令。 select curdate() AS 当前日期,curtime() AS 当前时间,datediff(2022-01-01, curdate()) AS 距离2022年1月1日还有天数;# &#xff08;2&#xff09;利…

知识点拓展——rsync同步命令的应用

Linux目录下有100万个文件&#xff0c;如何快速删除 当然了&#xff0c;首先我们想到的一定是rm -f删除&#xff0c;但是rm -f删除的话 会报错&#xff0c;提示无法删除&#xff0c;因为太长了&#xff0c;rm命令无法删除 [rootlocalhost opt]#mkdir files [rootlocalhost o…

Windows10蓝屏报错 inaccess boot device

当Windows 10操作系统启动时出现蓝屏错误“INACCESSIBLE_BOOT_DEVICE”时&#xff0c;这通常表明系统在尝试启动过程中无法识别或访问引导设备上的基本系统文件。这个问题可能是由以下几个原因引起的&#xff1a; 硬件兼容性问题&#xff1a; 硬盘控制器驱动不正确或丢失&#…

Go语言学习04~05 函数和面向对象编程

Go语言学习04-函数 函数是一等公民 <font color"Blue">与其他主要编程语言的差异</font> 可以有多个返回值所有参数都是值传递: slice, map, channel 会有传引用的错觉函数可以作为变量的值函数可以作为参数和返回值 学习函数式编程 可变参数 func s…

三种方式,浅谈 Cocos Creator 的动画添加

前言 虽然 Cocos 的官方文档对动画系统做了较详细的介绍&#xff0c;但是对于刚接触的同学&#xff08;比如我&#xff09;来说还是不太友好。尽管如此&#xff0c;我就按文档加社区帖子一起实践了一下。为了方便忘记后能快速捡起&#xff0c;所以就用我的方式结合使用场景&am…

python内存管理和垃圾回收一文详解(基于c语言源码底层逻辑)

引用计数器 首先我们大概回忆一下C语言中的环状双向链表&#xff0c;如图&#xff0c;在双向链表中对于一个结点来说会有前驱和后继&#xff1a; C语言中基本的定义方式如下&#xff1a; typedef struct {ElemType data; // 数据域Lnode* prior; // 前驱指针域Lnode* next;…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Hyperlink)

超链接组件&#xff0c;组件宽高范围内点击实现跳转。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。该组件仅支持与系统浏览器配合使用。 需要权限 使用网络时&#xff0c;需要申请权限ohos.per…

【PyTorch][chapter 22][李宏毅深度学习][ WGAN]【实战三】

前言&#xff1a; 本篇主要讲两个WGAN的两个例子&#xff1a; 1 高斯混合模型 WGAN实现 2 MNIST 手写数字识别 -WGAN 实现 WGAN 训练起来蛮麻烦的,如果要获得好的效果很多超参数需要手动设置 1&#xff1a; 噪声的维度 2: 学习率 3&#xff1a; 生成器&#xff0c;鉴别器…

【深度学习与神经网络】MNIST手写数字识别1

简单的全连接层 导入相应库 import torch import numpy as np from torch import nn,optim from torch.autograd import Variable import matplotlib.pyplot as plt from torchvision import datasets, transforms from torch.utils.data import DataLoader读入数据并转为ten…

mysql主从及备份

1.由于centOS7中默认安装了MariaDB,需要先进行卸载 rpm -qa | grep -i mariadb rpm -e --nodeps mariadb-libs-5.5.64-1.el7.x86_64查询下本机mysql是否卸载干净&#xff0c;若有残留也需要卸载 rpm -qa | grep mysql2.下载MySQL仓库并安装 wget https://repo.mysql.com//my…

C++: 多态实现原理解析

文章目录 1 静态多态实现原理 2 动态多态实现原理 code 1 静态多态 实现 函数重载&#xff0c;在编译器确定 函数重载的条件&#xff1a; 函数名相同参数个数不同&#xff0c;参数的类型不同&#xff0c;参数顺序不同返回值类型&#xff0c;不作为重载的标准 原理 函数名…

Android 开机启动的核心系统服务:你了解了吗?

Android 核心系统服务 目录 Android 核心系统服务 1. ActivityManagerService&#xff08;活动管理服务&#xff0c;简称AMS&#xff09; 2. PackageManagerService&#xff08;包管理服务&#xff0c;简称PMS&#xff09; 3. WindowManagerService&#xff08;窗口管理服务…