JavaScript基础 -- 迭代器与生成器

「JS 基础」迭代器和生成器 Iterator & Generator 入门 JavaScript的生成器(Generators)和迭代器(Iterators)是ES6引入的功能,使得开发者可以更方便地实现自定义的迭代逻辑。在创建自定义数据结构时,你可能需要提供一种遍历结构中元素的方法。迭代器和生成器允许你定义数据结构的迭代逻辑,使其能够使用标准的迭代协议进行遍历。实现一个自定义集合类(如图、树等),并通过生成器为其提供自定义的遍历逻辑。 阅读详情

1 理解迭代

在 JavaScript 中,计数循环就是一种简单的迭代
在这里插入图片描述
循环是迭代机制的基础,因为它可以指定迭代的次数,以及每次迭代要执行什么操作。每次循环都会在下一次迭代开始之前完成,而每次迭代的顺序都是事先定义好的

迭代会在一个有序集合上进行,"有序"可以理解为集合所有项都可以按照既定的顺序被遍历到,数组就是 JavaScript 中有序集合的最典型例子
在这里插入图片描述

通过这样的循环来执行存在以下问题:

1)迭代之前需要事先知道如何使用数据结构。数组中的每一项都只能先通过引用取得数组对象,通过 [] 操作符取得特定索引位置上的项,这种情况并不适用于所有数据结构

2)遍历顺序并不是数据结构固有的。通过递增索引来访问数据是特定于数组类型的方式,并不适用于其他具有隐式顺序的数据结构

ES5新增了 Array.prototype.forEach() 方法,这解决了单独记录索引和通过数组对象取得值的问题,但没办法标识迭代何时终止,因此这只适用于数组

很多语言通过原生语言结构解决了这个问题,我们无须事先知道如何迭代就能实现迭代操作,这个解决方案就是迭代器模式,ES6也支持了迭代器模式

2 迭代器模式

迭代器模式把有些结构称为"可迭代对象",因为它们实现了正式的 Iterable 接口,可以通过迭代器来逐一访问其中的元素

可迭代对象并不仅仅是数组或集合,它指的是任何可以通过某种遍历机制访问其元素的数据结构,这些元素是有限的,并且具有明确的遍历顺序,比如最开始提到的计数循环。该循环中生成的值是暂时性的,但循环本身是在执行迭代,计数循环和数组都具有可迭代对象的行为

PS:临时性可迭代对象可以实现为生成器

2.1 可迭代协议

实现 Iterable 接口(可迭代协议)意味着必须暴露一个属性作为"默认迭代器",而且这个属性必须使用特殊的 Symbol.iterator 作为键。这个默认迭代器属性必须引用一个迭代器工厂函数,调用这个工厂函数必须返回一个新迭代器
在这里插入图片描述

很多内置类型都实现了 Iterable 接口:字符串、数组、映射、集合、arguments对象、NodeList等 DOM 集合类型

实际写代码过程中,不需要显式调用这个工厂函数来生成迭代器。实现可迭代协议的所有类型都会自动兼容接收可迭代对象的任何语言特性,接收可迭代对象的原生语言特性包括:for-of循环、数组解构、扩展操作符、Array.from()、创建集合、创建映射、Promise.all()/race()、yield操作符,这些原生语言结构会在后台调用提供的可迭代对象的这个工厂函数,从而创建一个迭代器

如果对象原型链上的父类实现了 Iterable 接口,那这个对象也就实现了这个接口

2.2 迭代器协议

迭代器是一种一次性使用的对象,用于迭代与其关联的可迭代对象。迭代器 API 使用 next() 方法在可迭代对象中遍历数据,每次成功调用next(),都会返回一个 IteratorResult 对象,其中包含迭代器返回的下一个值;若不调用,则无法知道迭代器的当前位置

IteratorResult 对象包含两个属性:done 和 value

  • done是一个布尔值,表示是否还可以再次调用 next() 取得下一个值
  • value包含可迭代对象的下一个值(done为false),或者undefined(done为true)
    在这里插入图片描述

迭代器并不知道怎么从可迭代对象中取得下一个值,也不知道可迭代对象有多大,只要迭代器到达 done: true 状态,后续调用 next() 就一直返回undefined

每个迭代器都表示对可迭代对象的一次性有序遍历,不同迭代器的实例相互之间没有联系,只会独立地遍历可迭代对象

迭代器仅仅是使用游标来记录遍历可迭代对象的历程,如果可迭代对象在迭代期间被修改了,那么迭代器也会反映相应的变化
在这里插入图片描述
PS:迭代器维护着一个指向可迭代对象的引用,因此迭代器会阻止垃圾回收程序回收可迭代对象

2.3 提前终止迭代器

可选的 return() 方法用于指定在迭代器提前关闭时执行的逻辑,执行迭代的结构在想让迭代器知道它不想遍历到可迭代对象耗尽时,就可以"关闭"迭代器,可能的情况包括:

  • for-of循环通过 break、continue、return或throw 提前退出
  • 解构操作并未消费所有值

return()方法必须返回一个有效的 IteratorResult 对象,简单来说,可以只返回 done: true,因为这个返回值只会用在生成器的上下文中

如果迭代器没有关闭,则还可以继续从上次离开的地方继续迭代,比如数组的迭代器就是不能关闭的

在这里插入图片描述

因为 return() 方法是可选的,所以并非所有迭代器都是可关闭的。要知道某个迭代器是否可关闭,可以测试这个迭代器实例的 return 属性是不是函数对象。不过,仅仅给一个不可关闭的迭代器增加这个方法并不能让它变成可关闭的,因为调用 return() 不会强制迭代器进入关闭状态

3 生成器

3.1 生成器基础

生成器的形式是一个函数,函数名称前面加一个星号*,表示它是一个生成器。只要是可以定义函数的地方,就可以定义生成器。标示生成器函数的星号不受两侧空格的影响

PS:箭头函数不能用来定义生成器函数

调用生成器函数会产生一个生成器对象,它一开始处于暂停执行的状态,与迭代器相似,生成器对象也实现了 Iterator 接口,也具有 next() 方法,调用这个方法会让生成器开始或恢复执行

在这里插入图片描述

next() 方法的返回值类似于迭代器,有 done、value属性,函数体为空的生成器函数中间不会停留,调用一次 next() 就会让生成器到达 done: true 状态

在这里插入图片描述

value属性是生成器函数的返回值,默认值为undefined,可以通过生成器函数的返回值指定

在这里插入图片描述

生成函数只会在初次调用 next() 方法后开始执行,如下所示:

在这里插入图片描述

3.2 通过yield中断执行

生成器在遇到 yield 关键字之前会正常执行,遇到后执行会停止,函数作用域的状态会被保留。停止执行的生成器函数只能通过在生成器对象上调用 next() 来恢复执行

在这里插入图片描述

此时的 yield 关键字有点像函数的中间返回语句,它生成的值会出现在 next() 方法返回的对象里。通过 yield 退出的生成器函数会处在 done: false 状态,通过 return 退出的生成器函数会处在 done: true 状态

在这里插入图片描述

yield只能在生成器函数内部使用,用在其他地方会抛出错误。类似函数的 return,yield必须直接位于生成器函数定义中,出现在嵌套的非生成器函数中会抛出语法错误

在这里插入图片描述

1)生成器对象作为可迭代对象

在需要自定义迭代对象时,把生成器对象当作可迭代对象,这样使用生成器对象会特别有用。比如:我们需要定义一个可迭代对象,而它会产生一个迭代器,这个迭代器会执行指定的次数。使用生成器,可以通过一个简单的循环来实现:

在这里插入图片描述

传给生成器的函数可以控制迭代次数,在 n 为 0 时,while条件为假,循环退出,生成器函数返回

2)使用 yield 实现输入输出

yield还可以作为函数的中间参数使用,上一次让生成器函数暂停的 yield 会接收到传给 next() 方法的第一个值

PS:第一次调用 next() 传入的值不会被使用,因为这一次调用是为了开始执行生成器函数

在这里插入图片描述

yield可以同时用于输入和输出

在这里插入图片描述

因为函数必须对整个表达式求值才能确定要返回的值,所以在遇到 yield 时暂停执行并计算出要产生的值: foo;下一次调用 next() 传入了bar,作为交给同一个 yield 的值,这个值被确定为本次生成器函数要返回的值

yield并非只能使用一次,假设我们想定义一个生成器函数,它会根据配置的值迭代相应次数并产生迭代的索引

在这里插入图片描述

3) 产生可迭代对象

可以使用星号增强 yield 的行为,让它能够迭代一个可迭代对象,从而一次产出一个值

在这里插入图片描述

3.3 生成器作为默认迭代器

因为生成器对象实现了 Iterable 接口,而且生成器函数和默认迭代器被调用之后都产生迭代器,所以生成器很适合作为默认迭代器。下面是一个简单的例子,这个类的默认迭代器可以用一行代码产出类的内容:

在这里插入图片描述

for-of循环调用了默认迭代器(它恰好又是一个生成器函数)并产生了一个生成器对象,这个生成器对象是可迭代的,所以完全可以在迭代中使用

3.4 提前终止生成器

与迭代器类似,生成器也支持"可关闭",生成器对象除了之前迭代器那两种方法,还有第三种方法:throw(),return() 和 throw() 都可以用于强制生成器进入关闭状态

在这里插入图片描述

1) return()

提供给 return() 方法的值,就是终止迭代器对象的值。与迭代器不同,所有生成器对象都有 return() 方法,只要通过它进入关闭状态,就无法恢复了。后续调用 next() 会显示 done: true 状态,而提供的任何返回值都不会被存储或传播

在这里插入图片描述

2) throw()

throw()会在暂停的时候将一个提供的错误注入到生成器对象中,如果错误未被处理,生成器就会关闭

在这里插入图片描述

假如生成器函数内部处理了这个错误,那么生成器就不会关闭,而且还可以恢复执行,错误处理会跳过对应的yield

在这里插入图片描述

在上面这段代码中,生成器在 try/catch 块中的 yield 关键字处暂停执行。在暂停期间,throw() 方法向生成器对象内部注入了一个错误,这个错误会被 yield 抛出。由于 yield 抛出了这个错误,生成器就不会再产出值2,此时生成器继续执行,在下一次迭代再次遇到 yield 时产出了值3

PS:如果生成器对象还没有开始执行,那么调用 throw() 抛出的错误不会在函数内部被捕获,因为这相当于在函数块外部抛出了错误

JavaScript生成器详解与应用实践:generator-franks 本文还有配套的精品资源,点击获取 简介:生成器(Generator)是JavaScript中的一个重要特性,它提供了一种创建可暂停和恢复的迭代器的能力。这一特性特别适用于处理大量数据或异步操作,通过 function* 和 yield 关键字实现。生成器在简化代码、控制异步流程和实现惰性求值方面具有明显优势。本项目“generator-frank... 阅读详情

相关推荐

Matlab子图排版终极指南:从tight_subplot到tiledlayout的实战对比

本文深入对比Matlab中两大子图排版工具:社区经典函数tight_subplot与官方现代布局管理器tiledlayout。针对默认subplot产生的子图间距与边缘距离问题,详细解析两者的设计哲学、参数控制与实战应用,帮助用户根据版本与需求选择最佳方案,实现高效、精确且美观的多子图排版。

weixin_29048309的博客 360

JS的迭代器和可迭代对象详解

迭代器(iterator),是使用户在容器对象(container,例如链表或数组)上可以遍历访问的对象,使用该接口无需关心容器对象的内部实现细节。从迭代器的定义我们可以看出来,迭代器是帮助我们对某个数据结构进行遍历的对象。在JavaScript中,迭代器也是一个具体的对象,这个对象需要符合迭代器协议(iterator protocol):next方法要求:next方法是一个无参数或者有一个参数的函数,返回结果应当拥有以下两个属性的对象:1.done(boolean) : done返回一个布尔值: 可能是

m0_71485750的博客 5550

MAC M1用户必看:UTM虚拟机安装Win11全流程避坑指南(附驱动下载)

本文为MAC M1用户提供UTM虚拟机安装Win11的完整指南,涵盖镜像准备、驱动优化及性能调优等关键步骤。特别针对TPM 2.0验证、网络连接等常见问题提供解决方案,帮助用户高效运行Windows 11 ARM版。

weixin_29204205的博客 341

js中的迭代器与生成器(详解)

自定义遍历数据,要想起迭代器name'yiban',friend['duan','zhou','zhang','wei'],//索引变量//创建一个指针对象return{//创建next方法(必须)next()=>{//这里箭头函数解决this指向问题valuedonefalse};index++;}else{return{valuedonetrue}}}}}}}...

m0_63831957的博客 2133

对话系统简介

《文本上的算法》学习笔记1、问答型1.1、基于语义分析的方法1.2、基于信息抽取的方法1.3、端对端的方法2、任务型2.1、生成式模型( Generative Model )2.2、判别式模型( Discrimitive Model )2.3、规则系统3、闲聊型3.1、规则方法3.2、生成模型3.3、检索方法 个人认为NLP领域最难的方向可以说是阅读理解与文本生成/摘要,而对话系统,尤其是闲聊常常...

盘一哈nlp 6753

最新扣子(coze)案例:在coze上用DeepSeek+私有数据库、知识库,创建你的专属智能体

Gartner预测,到2026年,70%的企业将通过Al知识库实现「组织记忆外化」。数字化时代,数据已成为企业发展的核心资产。我们通过人工智能将知识库从“静态存储"升级为“智能服务”。让"沉睡宝藏"焕发新生,助力企业突破数据困局。

weixin_72689845的博客 2166

js中迭代器和生成器详解

你也可以自定义一个对象,使其成为可迭代对象,只要它实现了迭代器协议,即具有next()方法。示例:自定义对象的迭代器from: 1,to: 5,return {next() {} else {// 输出 1, 2, 3, 4, 5在这个例子中,myObj是一个自定义对象,我们通过定义方法,使得myObj成为一个可迭代对象。相同点都实现了迭代器协议,具有next()方法来返回数据。都能够按需返回数据,支持惰性求值。不同点迭代器:由一个对象实现,通常需要手动管理状态。生成器。

2401_87546826的博客 1742

Impala>Impala安装部署

文章目录1.安装前提2.下载安装包、依赖包3.虚拟机新增磁盘(可选)4.配置本地yum源5.安装Impala6.修改Hadoop、Hive配置7.修改impala配置8.启动、关闭impala服务 1.安装前提 集群提前安装好hadoop,hive。 hive安装包scp在所有需要安装impala的节点上,因为impala需要引用hive的依赖包。 hadoop框架需要支持C程序访问接口,查看下...

qq_44509920的博客 838

JavaScript的迭代器和生成器

JS迭代器是什么?for...of遍历的本质是什么?生成器函数又是什么?它的应用场景有哪些?异步编程中的async本质又是什么?

m0_61619549的博客 1362

LabVIEW状态机实战:用STM32+DHT11搭建温湿度监测系统(附完整VI源码)

本文详细介绍了如何利用LabVIEW状态机模式与STM32微控制器、DHT11温湿度传感器构建温湿度监测系统。通过硬件选型、状态机设计、LabVIEW程序实现及系统优化等环节,提供了一套完整的解决方案,并附有VI源码,助力开发者快速实现嵌入式温湿度监测应用。

weixin_42549723的博客 524

[LVGL] 刷新率优化

实验硬件:STM32F407ZGT6;2.4寸TFT-LCD模块(ILI9341驱动芯片、XTP2046触摸芯片)本文目标:lvgl的刷新率优化,解决拉帘子问题注意:本文在LVGL显示触摸代码移植完成的基础上进行,第一次使用lvgl可根据前文一步步移植,点击下方传送门查看相关文章传送门:STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(一)STM32F4驱动ILI9341的TFT-LCD触摸屏(HAL库)(二)[LVGL] 显示代码移植 基于STM32F4。

2301_77117901的博客 2784

JavaScript高级程序设计第四版学习记录-第七章迭代器与生成器

在软件开发领域,“迭代”的意思是按照顺序反复多次执行一段程序,通常会有明确的终止条件。 ECMAScript 6 规范新增了两个高级特性:迭代器和生成器。使用这两个特性,能够更清晰、高效、方便地实现迭代。 7.1 理解迭代 在 JavaScript 中,计数循环就是一种最简单的迭代: for (let i = 1; i <= 10; ++i) { console.log(i); } 循环是迭代机制的基础,这是因为它可以指定迭代的次数,以及每次迭代要执行什么操作。每次循环都会在下一次迭代开始之

qiao_qiao_happy的博客 751

HDMI接口及其在编程中的应用

在编程中,我们可以使用HDMI接口来控制和管理连接到计算机的HDMI设备。本文将介绍HDMI接口的基本原理以及如何在编程中使用HDMI接口。在编程中,我们可以使用HDMI接口来控制和管理连接到计算机的HDMI设备。本文介绍了HDMI接口的基本原理,并提供了使用Python编程语言和相关库实现HDMI接口应用的示例代码。我们可以使用编程语言提供的音频库来生成和播放音频,并将其通过HDMI接口输出到连接的设备上。我们可以使用编程语言提供的音频库来生成和播放音频,并将其通过HDMI接口输出到连接的设备上。

CodeByte的博客 804

批量生成数组_JavaScript【重温基础】13.迭代器和生成器

本文是 重温基础 系列文章的第十三篇。 今日感受:每次自我年终总结,都会有各种情绪和收获。本章节复习的是JS中的迭代器和生成器,常常用来处理集合。 前置知识: JavaScrip已经提供多个迭代集合的方法,从简单的for循环到map()和filter()。 迭代器和生成器将迭代的概念直接带入核心语言,并提供一种机制来自定义for...of循环的行为。 本文会将知识点分为两大部分,简单介...

weixin_39829497的博客 120

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

JavaScript基础之 迭代器和生成器

聊了一下迭代器的注意细节,以及生成器如何用,还有具体的例子演示细节。

u011863822的博客 298

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ES6中的迭代器生成器、反射与代理

一、迭代器(Iterator) 1、基础概念 迭代:从一个数据集合中按照一定的顺序,不断取出数据的过程。 迭代器(iterator):一个具有next方法的对象,next方法返回下一个数据并且能指示是否迭代完成 迭代器创建函数(iterator creator):一个返回迭代器的函数 2、JS中的迭代器 JS规定,如果一个对象具有next方法,并且该方法返回一个对象,该对象的格式如下: - nex...

漫漫前端路,进一寸有进一寸的欢喜 492

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

你知道的JS迭代器与生成器基础

迭代器(Iterator) 有时也称为遍历器 - 迭代器对象作用 为各种数据结构提供统一的访问接口 使数据结构的成员按照某种次序排列 统一的迭代方式for...of循环 1.可迭代(iterable) iterable:拥有Symbol.iterator属性的数据结构是可迭代的Symbol.iterator:值为迭代器生成函数原生可迭代的数据结构: Array Map Set String TypedArray arguments NodeList 这些数据结构均可以使用fo

qq_45272642的博客 405

javascript基础学习系列一百零九:迭代器与生成器

生成器对象实现了 Iterable 接口,因此可用在任何消费可迭代对象的地方。这个例子创建了一个名为 person 的对象,而且有三个属性(name、age 和 job)和一个方法(sayName())。后者包含迭代器返回的当前值。迭代器是一个可以由任意对象实现的接口,支持连续获取对象产出的每一个值。默认迭代器就像一个迭代器工厂,也就是一个函数,调用之后会产生一个实现 Iterator 接口的对象。这个例子中的 person 对象跟前面例子中的 person 对象是等价的,它们的属性和方法都一样。

m0_68635815的博客 398

(基础)JavaScript生成器来替代迭代器

JavaScript生成器来替代迭代器写法,简化迭代器代码

次顶级的博客 259

javascript基础学习系列四百七十:迭代器与生成器

代对象”(iterable),因为它们实现了正式的Iterable 接口,而且可以通过迭代器Iterator 消费。迭代的英文“iteration”源自拉丁文itero,意思是“重复”或“再来”。迭代器无须了解与其关联的可迭代对象的结构,只需要知道如何取得连续的。因为数组有已知的长度,且数组每一项都可以通过索引获取,所以整个数组可以通过递增索引来遍历。开头提到的计数循环。该循环中生成的值是暂时性的,但循环本身是在执行迭代。循环是迭代机制的基础,这是因为它可以指定迭代的次数,以及每次迭代要执行什么操作。

m0_68635815的博客 463

Kun 的 PPT 设计增强:视觉方向选择、有界缩略图导航与确定性 OOXML 几何质量门禁

本文解析 Kun 开源仓库中 `enhance-ppt-design-preview-qa` 变更的设计方案(OpenSpec design 文档)。Kun 的原生 PPT 工作流是一个受治理的子工作流(governed child workflow),它会持久化设计计划指纹、生成结构化的幻灯片评审包、通过本地 WASM 导出器产出可编辑的 PPTD,并在发布前校验 OOXML 包。本次变更围绕四

gitblog_00016的博客 426

JS 基础之异步(四):Generator(生成器、迭代器源码实现)

Step3:Generator Generator 是什么 **生成器(Generator)**对象是ES6中新增的语法,和Promise一样,都可以用来异步编程。但与Promise不同的是,它不是使用JS现有能力按照一定标准制定出来的,而是一种新型底层操作,async/await就是在它的基础上实现的。 generator对象是由generator function返回的,符合可迭代协议和迭代器...

我本可以容忍阳光,如果我不曾见过太阳,然而阳光已使我荒凉,成为更新的荒凉。 1316

javascript基础学习系列一百零七:迭代器与生成器

为此,生成器函数必须接收一个可迭代对象,产出该对象中的每一个值,并且对每个值进行递归。这个实现可以用来测试某个图是否连通,即是否没有不可到达的节点。只要从一个节点开始,然后尽力访问每个节点就可以了。因为生成器对象实现了 Iterable 接口,而且生成器函数和默认迭代器被调用之后都产生迭代器,所以生成器格外适合作为默认迭代器。这里,for-of 循环调用了默认迭代器(它恰好又是一个生成器函数)并产生了一个生成器对象。这个生成器对象是可迭代的,所以完全可以在迭代中使用。生成器作为默认迭代器。

wanmeijuhao的博客 383

javascript基础学习系列一百零六:迭代器与生成器

因为 yield*实际上只是将一个可迭代对象序列化为一连串可以单独产出的值,所以这跟把 yield。使用递归生成器结构和 yield*可以优雅地表达递归算法。下面是一个图的实现,用于生成一个随。果就是生成器函数会递归地减少计数器值,并实例化另一个生成器对象。从最顶层来看,这就相当于创。在这个例子中,每个生成器首先都会从新创建的生成器对象产出每个值,然后再产出一个整数。放到一个循环里没什么不同。建一个可迭代对象并返回递增的整数。

m0_68635815的博客 447
上一篇: JavaScript基础 -- 变量、作用域与内存
下一篇: 从前端视角看设计模式之创建型模式篇
ZoeLandia
博客等级 码龄6年 734粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值