JavaScript:生成器函数

news2024/11/24 5:38:52

在介绍生成器函数之前先了解一下ES6的一个关键字,名为yield

yield关键字,可以让代码在其出现的地方暂停执行,它只能在生成器函数内部使用。

生成器函数

生成器函数的语法比较简单在普通函数声明的时候在函数名前面添加一个*即可,如下所示:

function *gen(){}

当函数被调用时会返回一个返回值,但是生成器函数与普通函数的返回值有些区别。

普通函数如果没有使用return返回时,接收到的是undefined,而生成器函数不管有没有return都返回一个对象,这个对象被称为迭代器,我们可以通过这个对象控制迭代器的执行。通常,使用迭代器的next方法,让其继续执行。

let x = 0;
function *gen(){
	console.log(x);
	yield x++;
}
let itr = gen();
console.log(itr)

在这里插入图片描述

根据上面的结果我们可以知道,生成器函数在被调用时并不会开始执行代码。得到了一个对象,这也验证了上文所言。
接下来,我们让它继续执行,需要调用next方法。

let x = 0;
function *gen(){
	console.log(x);
	yield x++;
}
let itr = gen();
console.log(itr)
itr.next();
console.log(x)

在这里插入图片描述
从上面的结果来看,next方法也验证了前文所言。
当我们调用next方法时,next方法也会返回一个对象,这个对象包含一个value属性,value属性的值是当前yield语句的结果。

let x = 0;
function *gen(){
	console.log(x);
	yield x++;
}
let itr = gen();
console.log(itr)
let res = itr.next();
console.log(res)

在这里插入图片描述
我们根据结果可以看到,除了value属性,还可以看到一个done属性,done属性的值表示迭代器的完成状态,为true表明完成迭代,为false,表明没有完成迭代。

如果一个生成器函数中使用return,我们需要得到return的值,这时候需要使用next方法返回的对象的value属性得到返回的值。

let x = 0;
function *gen(){
	console.log(x);
	yield x++;
	return x;
}
let itr = gen();
let res = itr.next();
console.log(res.value);
res = itr.next();
console.log(res.value,res);
res = itr.next();
console.log(res);

在这里插入图片描述
根据输出的第三行,我们可以看到输出的值是1,与预想的一样,同时done属性也为true,说明运行到return语句。当我们再次运行next方法时,此时函数已经执行完毕,不在执行,也就没有返回值,因此是undefined。

但是在返回1之前,还有一个值,这个值是yield x++; 语句的返回值,x++的返回值是0,因此value属性是0

这样一个完整的迭代器运行流程我们就了解了。

接下来,我们再了解一下next方法。之前我们知道next方法返回一个对象,可以通过value属性得到返回值。

next方法也可以接收一个值

let x = 0;
function *gen(){
	console.log(yield);
	 x++;
	return x;
}
let itr = gen();
let res = itr.next(6);
console.log(res);
res = itr.next(7);
console.log(res);

在这里插入图片描述
根据结果我们可以知道,第一个next传递参数并不会被接收,规范和所有兼容浏览器都会默默丢弃传递给第一个next()的任何东西。传值过去仍然不是一个好思路,因为你创建了沉默的无效代码,这会让人迷惑。因此,启动生成器时一定要用不带参数的next()。

只有从第二个next开始传递的参数才会被接收,由此,我们可以总结,next传递的值被上一个yield接收,next与field相差一个间隔。

那么为什么会产生这个差距呢?

因为第一个next(…)总是启动一个生成器,并运行到第一个yield处。不过,是第二个next(…)调用完成第一个被暂停的yield表达式,第三个next(…)调用完成第二个yield,以此类推。

以上就是生成器函数的基本使用,那么生成器函数到底有什么用或者说能够应用在什么场景呢?

生成器函数可以应用在异步任务中,当一个异步任务没有返回值时我们可以让程序在此处暂停当有返回值时在调用next继续执行。

示例

        function run(gen) {
  var args = [].slice.call(arguments, 1), it;

  // 在当前上下文中初始化生成器
  it = gen.apply(this, args);

  // 返回一个promise用于生成器完成
  return Promise.resolve()
    .then(function handleNext(value) {
      // 对下一个yield出的值运行
      var next = it.next(value);

      return (function handleResult(next) {
        // 生成器运行完毕了吗?
        if (next.done) {
          return next.value;
        }
        // 否则继续运行
        else {
          return Promise.resolve(next.value)
            .then(
              // 成功就恢复异步循环,把决议的值发回生成器
              handleNext,
              // 如果value是被拒绝的promise,
              // 就把错误传回生成器进行出错处理
              function handleErr(err) {
                return Promise.resolve(it.throw(err)).then(handleResult);
              }
            );
        }
      })(next);
    });
}

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

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

相关文章

openxr runtime Monado 源码解析 源码分析:Prober设备发现和管理 system device HMD target instance

monado系列文章索引汇总:openxr runtime Monado 源码解析 源码分析:源码编译 准备工作说明 hello_xr解读openxr runtime Monado 源码解析 源码分析:整体介绍 模块架构 模块作用 进程 线程模型 整体流程openxr runtime Monado 源码解析 源码分…

计算机网络4小时速成:物理层,功能特性,通信系统模型,分类,调制,曼彻斯特编码,信噪比,香农定理,复用技术,同轴电缆,中继器

计算机网络4小时速成:物理层,功能特性,通信系统模型,分类,调制,曼彻斯特编码,信噪比,香农定理,复用技术,同轴电缆,中继器 2022找工作是学历、能力…

[附源码]计算机毕业设计JAVA基于jsp的网上点餐系统

[附源码]计算机毕业设计JAVA基于jsp的网上点餐系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM m…

Proxy 代理对象使用详解即原理总结

Proxy 代理对象使用详解即原理总结 Proxy简单介绍 ECMAscript 6新增的代理可以给目标对象定义一个关联的代理对象,而这个代理对象可以作为抽象的目标对象来使用,在对目标对象的各种操作影响目标对象之前,可以在代理对象中对这些操作加以控制…

【python与数据分析】Matplotlib数据可视化

目录 前言 一、数据可视化库matplotlib 1.综述 2.pyplot基础语法 (1)创建画布与创建子图 (2)添加画布内容 (3)保存与展示图形 (4)设置pyplot的动态rc参数 二、绘制折线图 …

Python面向对象总结一

还记得第一次接触Python是在刚刚进入大学的第一个学期,之后就没有再使用过python。虽然基本语法,内置函数等没有忘记,但最近的学习中,一直在用python、matlab混合编程,零零散散的知识点、模模糊糊的记忆,有…

5G无线技术基础自学系列 | 传统无线网络架构

素材来源:《5G无线网络规划与优化》 一边学习一边整理内容,并与大家分享,侵权即删,谢谢支持! 附上汇总贴:5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 在4G网络中, 无线侧基本完成…

Anaconda配置镜像源

目录 一、首先生成 Anaconda的 .condarc配置文件: 二、命令行方式配置镜像源 三、可视化界面的方式配置镜像源 一、首先生成 Anaconda的 .condarc配置文件: 打开 Anaconda prompt,敲命令: conda config 查看 .condarc 中的源…

MySQL 增删改查进阶 — 数据库约束

文章目录数据库约束1.约束类型1.1 not null1.2 unique 唯一约束1.3 主键约束 primary key1.4 default 默认值1.5 外键约束 foreign key数据库约束 约束就是让数据库帮助程序猿更好的检查数据是否正确。 1.约束类型 not null - 提示某列不能存储 NULL 值。 允许为空&#xff…

wav to image concat 版

🍿*★,*:.☆欢迎您/$:*.★* 🍿 目录 背景 正文 总结 背景描述

STM32矩阵按键

矩阵按键原理 本实验使用STM32F103单片机,主题代码通用的。 如果每个按键占用一个GPIO引脚,对于使用多个按键来说就是一种资源的浪费,因此当我们在设计时,可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。 矩阵按键相对于独立…

Go 语言搭建个人博客(qiucode.cn 重构篇 三)

1、读取配置文件 项目中如数据库连接、邮箱配置等这些信息一般会被写入一个文件,而通过编码在程序中读取想要的配置信息。 本项目使用yaml文件作为配置文件,配合第三方库viper来读取yaml配置文件。 go get -u github.com/spf13/viper在项目根目录新建一个yaml文件,内容如…

数学杂谈:限制条件下的均匀分布考察

数学杂谈:限制条件下的均匀分布考察 1. 问题描述2. 问题解答 1. 答案2. 解析3. 蒙特卡洛模拟 3. 离散情况延拓 1. 正整数的情况2. 整数的情况3. N→∞N \to \inftyN→∞的情况 4. 误区分析 1. 问题描述 假设x1,...,xnx_1, ..., x_nx1​,...,xn​均为0∼10 \sim 10…

思科防火墙解析(ASA)

♥️作者:小刘在C站 ♥️每天分享云计算网络运维课堂笔记,一起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放。 目录 一. 防火墙的分类, 二. 发展史, 三. 思科防火墙技术应用的…

[附源码]java毕业设计铁东社区新冠病毒疫苗接种管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

山东大学线性代数-4-线性方程组

目录 4.1 齐次线性方程组 4.1.1 齐次线性方程组的定义 4.1.2 方程组的三种形式 4.1.3 齐次线性方程组解的性质 4.1.4 行最简形矩阵 4.1.5 两个例题 4.2 基础解系的求法 4.2.1 求解步骤 4.2.2 例题 4.3 非齐次线性方程组 4.3.1 相关概念 4.3.2 非齐次线性方程组的有…

编译安装php扩展

1. 切换到要安装的扩展的目录下 2. 执行phpize(在扩展目录里 可以写自己电脑里的绝对路径) ../../bin/phpize 3. 然后执行 ./configure ./configure 4. 没问题的话 make 然后 make install make 运行之后出现下图就说明可以下一步了 运行 make install make install 出现…

GitHub使用教程

目录概要一. 下载git二. 初始化本地仓库设置签名查看状态,三大分区,添加,提交操作查看状态,三大分区添加查看提交历史查看提交历史的其他指令如何进行版本切换基于索引值基于^符号进行版本切换基于~符号进行版本切换reset指令的参…

【OS】新国立nus操作系统知识点(中文版)

文章目录1. Introduction to OS本章涉及1.1 什么是操作系统?1.2 为什么我们需要操作系统?抽象 Abstraction控制程序Summary1.3 现代操作系统分类1.4 操作系统结构OS结构OS是一个程序OS的实现单片OS Monolithic OS微核OS Microkernel虚拟机 Virtual Machi…

22071.11.20作业

在串口工具进行输入: echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led2灯点亮 echo 0 > /dev/myled1 ---->led2灯熄灭 echo 1 > /dev/myled2 ----&g…