Javascript 可迭代对象与yeild

一、可迭代对象(Iterable object)

Javascript 可迭代对象是指实现了Symbol.iterator方法的对象,该方法返回一个迭代器对象,可以通过迭代器对象来遍历对象中的元素。常见的可迭代对象包括数组、字符串、Map、Set等。可以使用for...of循环或者使用迭代器的next方法来遍历可迭代对象中的元素。

二、Symbol.iterator

Symbol.iterator是一个内置的Symbol对象,它是用来定义一个对象的默认迭代器的。当一个对象被迭代时(比如使用for…of循环),它的Symbol.iterator方法会被调用,返回一个迭代器对象。这个迭代器对象具有next()方法,用于在对象中的元素上进行迭代。

通过实现Symbol.iterator方法,我们可以使一个对象成为可迭代的,从而可以使用for…of循环或者其他迭代器方法来遍历对象中的元素。常见的可迭代对象包括数组、字符串、Map、Set等。

下面是一个简单的示例,展示了如何使用Symbol.iterator来实现一个可迭代对象:

const days = {start: new Date('2023-10-01'),end: new Date('2023-10-05'),[Symbol.iterator]() {return {current: this.start,last: this.end,next() {if(this.current.getTime() <= this.last.getTime()) {const value = this.currentthis.current = new Date(this.current.getTime() + 24 * 3600 * 1000)return {done: false,value}} else {return {done: true}}}}}
}for(let day of days) {console.log(day)
}

在这里插入图片描述

为了让 days对象可迭代(也就让 for…of 可以运行)我们需要为对象添加一个名为 Symbol.iterator 的方法(一个专门用于使对象可迭代的内建 symbol)。

当 for…of 循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个 迭代器(iterator) —— 一个有 next 方法的对象

当 for…of 循环希望取得下一个数值,它就调用这个对象的 next() 方法。
next() 方法返回的结果的格式必须是 {done: Boolean, value: any},当 done=true 时,表示循环结束,否则 value 是下一个值。

在这里我们也可以结合yield来实现:

const days = {start: new Date('2023-10-01'),end: new Date('2023-10-05'),*[Symbol.iterator]() {let current = this.startlet last = this.endwhile(current.getTime() <= last.getTime()) {value = currentcurrent = new Date(current.getTime() + 24 * 3600 * 1000)yield value}}
}for(let day of days) {console.log(day)
}

迭代对象的实现方式:

① 可迭代对象必须实现 Symbol.iterator 方法。objSymbol.iterator 的结果被称为 迭代器(iterator)。由它处理进一步的迭代过程。
②一个迭代器必须有 next() 方法,它返回一个 {done: Boolean, value: any} 对象,这里 done:true 表明迭代结束,否则 value 就是下一个值。
Symbol.iterator 方法会被 for…of 自动调用,但我们也可以直接调用它。

注:内建的可迭代对象例如字符串和数组,都实现了 Symbol.iterator。

三、yeild

在JavaScript中,yield是ES6(ECMAScript 6)中的一种关键字,用于生成器函数中。通过yield,我们可以在生成器函数中暂停执行并返回一个迭代器对象给调用者,再次调用时可以从上一次暂停的地方继续执行。

yield 的应用场景包括但不限于以下几个方面:

1.惰性求值

通过生成器函数和 yield 关键字,可以实现惰性求值,即只在需要时才计算值。这对于处理大量数据或者需要耗时计算的场景非常有用。

在 JavaScript 中,生成器函数中的 yield语句可以实现惰性求值。惰性求值是一种延迟计算的策略,即只在需要值的时候才进行计算。生成器函数的 yield语句可以用于实现这种惰性求值的特性。

下面是一个示例,演示了如何在生成器函数中使用 yield 实现惰性求值:

function* lazyEvaluation() {let result1 = yield calculateResult1();console.log(result1); // 这里会输出第一个结果let result2 = yield calculateResult2();console.log(result2); // 这里会输出第二个结果
}function calculateResult1() {console.log("Calculating result 1");return 100;
}function calculateResult2() {console.log("Calculating result 2");return 200;
}let generator = lazyEvaluation();// 调用 next() 时,并不会立即计算结果,而是在需要值的时候才进行计算
let next1 = generator.next(); // 这里会输出 "Calculating result 1"
let next2 = generator.next(); // 这里会输出第一个结果,然后输出 "Calculating result 2"
let next3 = generator.next(); // 这里会输出第二个结果

在上面的示例中,lazyEvaluation 是一个生成器函数,其中使用了 yield 语句来实现惰性求值。当调用生成器函数的 next() 方法时,计算并返回结果的操作被延迟到真正需要值的时候才进行。这样可以节省计算资源,并且使得程序更加高效。

2.异步编程

yield 可以与异步操作结合使用,例如使用 Promise 对象。通过 yield 可以简化异步操作的编写,使代码更加清晰易懂。

在 JavaScript 中,生成器函数中的 yield 语句可以与异步编程结合使用,从而实现更加灵活和可读性更高的异步代码。通过结合生成器函数和异步操作,可以避免回调地狱(callback hell)和使用 Promise 的 then 方法时出现的嵌套问题。

下面是一个示例,演示了如何在生成器函数中使用 yield 语句实现异步编程:

function fakeAsyncAPI(value, delay) {return new Promise(resolve => {setTimeout(() => {resolve(value);}, delay);});
}function* asyncOperation() {let result1 = yield fakeAsyncAPI('First result', 1000);console.log(result1); // 输出: First resultlet result2 = yield fakeAsyncAPI('Second result', 500);console.log(result2); // 输出: Second result
}function runAsyncOperation() {let generator = asyncOperation();function handleAsyncOperation(result) {let next = generator.next(result);if (next.done) {return;}next.value.then(res => {handleAsyncOperation(res);});}handleAsyncOperation();
}runAsyncOperation();

3.无限序列

生成器函数可以用于创建无限序列,例如斐波那契数列、无限递增的整数等。

在 JavaScript 中,可以使用生成器函数和 yield 语句来创建无限序列。生成器函数可以用于按需生成序列中的元素,而不需要提前将整个序列存储在内存中。

下面是一个示例,演示了如何使用生成器函数和 yield 语句创建一个无限序列:

function* infiniteSequence() {let i = 0;while (true) {yield i;i++;}
}let generator = infiniteSequence();console.log(generator.next().value); // 输出: 0
console.log(generator.next().value); // 输出: 1
console.log(generator.next().value); // 输出: 2
// 以此类推,可以无限地获取序列中的下一个元素

4.状态机

yield 可以用于实现状态机,通过不同的 yield 值来表示不同的状态。

在 JavaScript 中,可以使用生成器函数和 yield 语句来实现状态机。状态机是一种用于描述对象在不同状态下的行为的数学模型,它包含有限个状态以及在这些状态之间的转换。

下面是一个简单的示例,演示了如何使用生成器函数和 yield 语句来实现一个简单的状态机:

function* stateMachine() {let state = 'start';while (true) {let input = yield state;if (input === 'go') {state = 'running';} else if (input === 'stop') {state = 'stopped';}}
}let machine = stateMachine();
console.log(machine.next().value); // 输出: start
console.log(machine.next('go').value); // 输出: running
console.log(machine.next('stop').value); // 输出: stopped

在上面的示例中,stateMachine 是一个生成器函数,它模拟了一个简单的状态机。每次调用生成器函数的 next() 方法时,会返回当前状态,并等待传入下一个输入。根据输入的不同,状态机会根据规则转换到不同的状态。

通过使用生成器函数和 yield 语句,我们可以很容易地实现状态机的逻辑。这种方式使得状态机的代码更加清晰和易于理解,同时也可以方便地实现状态之间的转换逻辑。

5.协程函数

实现函数暂停和恢复的协程模式。

在 JavaScript 中,yield 关键字通常与生成器函数(Generator
Function)一起使用,用于实现协程(Coroutine)。协程是一种并发编程的模型,它允许在不同的执行上下文之间进行切换,并且可以保存和恢复执行状态。通过使用yield 和生成器函数,可以实现一种简单的协程模型。

在协程函数中,yield 可以暂停函数的执行,并且可以返回一个值给调用者。调用者可以在需要时恢复协程的执行,并且可以传入一个值作为协程函数中 yield 的结果。

下面是一个简单的示例,展示了如何使用生成器函数和 yield 实现协程函数:

function* coroutineFunction() {let result = yield "First";console.log(result);result = yield "Second";console.log(result);
}let coroutine = coroutineFunction();console.log(coroutine.next()); // 输出: { value: 'First', done: false }
console.log(coroutine.next("Hello")); // 输出: Hello// 输出: { value: 'Second', done: false }
console.log(coroutine.next("World")); // 输出: World// 输出: { value: undefined, done: true }

在这个示例中,coroutineFunction 是一个生成器函数,通过 yield 实现了协程的暂停和恢复。在调用 coroutine.next() 时,协程函数会在每个 yield 处暂停,并返回一个对象,包含当前的值和是否执行完毕的标志。调用 coroutine.next(value) 时,传入的值会作为上一个 yield 的结果,并且协程函数会继续执行直到下一个 yield 处。

四、可迭代(iterable)和类数组(array-like)

这两个术语看起来差不多,但其实大不相同。
Iterable 如上所述,是实现了 Symbol.iterator 方法的对象。
Array-like 是有索引length 属性的对象,所以它们看起来很像数组。

① 一个可迭代对象也许不是类数组对象。
② 一个类数组对象可能不可迭代。比如:

let arrayLike = { // 有索引和 length 属性 => 类数组对象0: "Hello",1: "World",length: 2
};// Error (no Symbol.iterator)
for (let item of arrayLike) {}

③ 一个对象,可能既是类数组对象,又是可迭代对象。比如,字符串既是可迭代的(for…of 对它们有效),又是类数组的(它们有数值索引和 length 属性)。

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

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

相关文章

Redis布隆过滤器BloomFilter

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

Unreal Engine游戏引擎的优势

在现在这个繁荣的游戏开发行业中&#xff0c;选择合适的游戏引擎是非常重要的。其中&#xff0c;Unreal Engine作为一款功能强大的游戏引擎&#xff0c;在业界广受赞誉。那Unreal Engine游戏引擎究竟有哪些优势&#xff0c;带大家简单的了解一下。 图形渲染技术 Unreal Engin…

遇见sql语句拼装报错 sql injection violation, syntax error: syntax error, expect RPAREN

在使用PostgreSql瀚高数据库时&#xff0c;相同的语句 select * from public.files_info fi where fi.file_size notnull 在DBever能执行&#xff0c;但是在spring中报错 在spring中JPA版本问题导致&#xff0c;不支持这种写法&#xff0c;会识别为sql注入风险&#xff0c;应…

硅像素传感器文献调研(四)

写在前面&#xff1a; 好喜欢这种短论文哈哈哈哈哈 感觉这篇文献已经提到了保护环的概念啊&#xff0c;只不过叫的是&#xff1a;场限制环。 1986——高压功率器件场终端横向掺杂的变化 0.摘要 对于高压平面结提出了一个简单的新概念。通过在氧化物掩模中的小开口和随后的驱…

python如何读取被压缩的图像

读取压缩的图像数据&#xff1a; PackBits 压缩介绍&#xff1a; CCITT T.3 压缩介绍&#xff1a; 读取压缩的图像数据&#xff1a; 在做图像处理的时候&#xff0c;平时都是使用 函数io.imread() 或者是 函数cv2.imread( ) 函数来读取图像数据&#xff0c;很少用PIL.Image…

Grafana Loki 组件介绍

Loki 日志系统由以下3个部分组成&#xff1a; Loki是主服务器&#xff0c;负责存储日志和处理查询。Promtail是专为loki定制的代理&#xff0c;负责收集日志并将其发送给 loki 。Grafana用于 UI展示。 Distributor Distributor 是客户端连接的组件&#xff0c;用于收集日志…

2022年全国职业院校技能大赛(高职组)“云计算”赛项赛卷①第一场次:私有云

2022年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算”赛项赛卷1 第一场次&#xff1a;私有云&#xff08;30分&#xff09; 目录 2022年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算”赛项赛卷1 第一场次&#xff1a;私有云&#xff0…

【Linux学习笔记】解析Linux系统内核:架构、功能、工作原理和发展趋势

操作系统是一个用来和硬件打交道并为用户程序提供一个有限服务集的低级支撑软件。一个计算机系统是一个硬件和软件的共生体&#xff0c;它们互相依赖&#xff0c;不可分割。计算机的硬件&#xff0c;含有外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的发动机。但是…

磁盘相关知识

一、硬盘数据结构 1.扇区&#xff1a; 盘片被分为多个扇形区域&#xff0c;每个扇区存放512字节的数据&#xff08;扇区越多容量越大&#xff09; 存放数据的最小单位 512字节 &#xff08;硬盘最小的存储单位是扇区&#xff0c;512 个字节&#xff0c;八个扇区组成一块&…

FPGA - 231227 - 5CSEMA5F31C6 - 电子万年历

TAG - F P G A 、 5 C S E M A 5 F 31 C 6 、电子万年历、 V e r i l o g FPGA、5CSEMA5F31C6、电子万年历、Verilog FPGA、5CSEMA5F31C6、电子万年历、Verilog 顶层模块 module TOP(input CLK,RST,inA,inB,inC,switch_alarm,output led,beep_led,output [41:0] dp );// 按键…

听GPT 讲Rust源代码--src/tools(29)

File: rust/src/tools/clippy/clippy_lints/src/unused_peekable.rs 在Rust源代码中&#xff0c;rust/src/tools/clippy/clippy_lints/src/unused_peekable.rs这个文件是Clippy工具中一个特定的Lint规则的实现文件&#xff0c;用于检测未使用的Peekable迭代器。 Peekable迭代器…

每日一题:LeetCode-LCR 179. 查找总价格为目标值的两个商品

每日一题系列&#xff08;day 16&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

大厂前端面试题总结(百度、字节跳动、腾讯、小米.....),附上热乎面试经验!

先简单介绍下自己&#xff0c;我“平平无奇小天才”一枚&#xff0c;毕业于南方普通985普通学生&#xff0c;有幸去百度、字节面试&#xff0c;感觉大公司就是不一样&#xff0c;印象最深的是字节&#xff0c;所以有必要总结一下面试经验&#xff0c;以及面试中遇到的一些问题&…

腾讯云服务器和轻量服务器选哪个好(各自的优势区别)

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…

Rust安装(Windows)

安装Rust 进入Rust官网&#xff0c;下载Rustup&#xff08;Rust安装器和版本管理工具&#xff09; 下载rustup-init.exe后双击运行&#xff0c;进入以下界面&#xff1a; 1&#xff09;通过 visual studio community 安装程序快速安装 2&#xff09;手动安装必备组件 3&#x…

系统和应用的分布式实时性能和健康监控,对系统中实时发生的所有事情的全面检测,开箱即用、零配置、零依赖,高度互动的 Web 仪表板中查看结果

系统和应用的分布式实时性能和健康监控,对系统中实时发生的所有事情的全面检测,开箱即用、零配置、零依赖,高度互动的 Web 仪表板中查看结果。 NetData 是一个用于系统和应用的分布式实时性能和健康监控工具。它提供了对系统中实时发生的所有事情的全面检测。你可以在高度互…

AWS SSM中切换AWS不同的profile

问题 在自己的开发笔记本上面&#xff0c;通过AWS SSM方式访问EC2服务&#xff0c;只需要通过简单的命令就可以访问EC2了&#xff0c;如下&#xff1a; aws ssm start-session --target i-xxxx12350这个命令就是利用aws命令行工具中ssm提供的会话管理能力访问ec2服务&#xf…

YOLOv5改进 | 2023主干篇 | 华为最新VanillaNet主干替换Backbone实现大幅度长点

一、本文介绍 本文给大家来的改进机制是华为最新VanillaNet网络&#xff0c;其是今年最新推出的主干网络&#xff0c;VanillaNet是一种注重极简主义和效率的神经网络架构。它的设计简单&#xff0c;层数较少&#xff0c;避免了像深度架构和自注意力这样的复杂操作(需要注意的是…

HTML使用JavaScript的三种方式

要使用 JavaScript&#xff0c;你可以在 HTML 文件中的 <script> 标签中编写代码&#xff0c;或者将代码保存到一个单独的 .js 文件中并在 HTML 文件中引入。以下是一些常用的 JavaScript 使用方式&#xff1a; 内联 JavaScript&#xff1a;在 HTML 文件的 <script&g…

Erlang、RabbitMQ下载与安装教程(windows超详细)

目录 安装Erlang 1.首先安装RabbitMQ需要安装Erlang环境 2.点击下载好的.exe文件进行傻瓜式安装,一直next即可 3.配置Erlang环境变量 安装RabbitMQ 1.给出RabbitMQ官网下载址&#xff1a;Installing on Windows — RabbitMQ&#xff0c;找到 2.配置RabbitMQ环境变量&#xff0…