当前位置: 首页 > news >正文

ES6学习-Generator

Generator

种异步编程解决方案

  1. 函数会返回一个遍历器对象
  2. 语法上:Generator 函数是一个状态机,封装了多个内部状态。
  3. 形式上:Generator 函数是一个普通函数;
  4. 有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,
function* helloWorldGenerator() {yield 'hello';yield 'world';return 'ending';
}
var hw = helloWorldGenerator();

它内部有两个yield表达式(helloworld),即该函数有三个状态:hello,world 和 return 语句(结束执行)。

  • 调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。

总结一下

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着valuedone两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

yield 表达式

遍历器对象的next方法的运行逻辑如下。

yield表达式是暂停执行的标记,而next方法可以恢复执行。

yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行;“惰性求值”

yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。

  1. 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
  2. 下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
  3. 如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
  • yield表达式如果用在另一个表达式之中,必须放在圆括号里面。
function* demo() {console.log('Hello' + (yield)); // OKconsole.log('Hello' + (yield 123)); // OK
}
  • yield表达式用作函数参数或放在赋值表达式的右边,可以不加括号。
function* demo() {foo(yield 'a', yield 'b'); // OKlet input = yield; // OK
}

与 Iterator 接口的关系

由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性

含义:Generator 与状态机

没懂协程与子例程

next() 方法

yield表达式本身没有返回值 undefined

next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值

function* f() {let a = 2 * (yield 1) // 2 * undefindconsole.log('a:', a) //NaNlet b = 2 * (yield 2)console.log(a, b)//NaN, 20return 1
}
let a = f()
console.log(a.next())//{value: 1, done: false}
console.log(a.next())//{value: 2, done: false}
console.log(a.next(10))//{value: 1, done: true}

for…of 循环

yied*表达式

在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。

function* foo() { yield 'a'; yield 'b'; }
function* bar() {yield 'x';for (let i of foo()) {yield i}; yield 'y';
}
for (let v of bar()){ console.log(v); }
  • 在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。
  • 提供了yield*表达式,作为解决办法,用来在一个 Generator 函数里面执行另一个 Generator 函数。
function* bar() { yield 'x'; yield* foo(); yield 'y'; }
// 等同于
function* bar() { yield 'x'; yield 'a'; yield 'b'; yield 'y'; }

语法角度:如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*表达式。

如果yield*后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。

function* gen(){ yield* ["a", "b", "c"]}
gen().next() // { value:"a", done:false }
let read = (function* () {yield 'hello';yield* 'hello';
})();
read.next().value // "hello"
read.next().value // "h"

如果被代理的 Generator 函数有return语句,结果是不一样的,‘

function* foo() { yield 'a'; yield 'b'; }
function* bar() {yield 'x';for (let i of foo()) {yield i}; yield 'y';
}
for (let v of bar()){ console.log(v); }

throw

throw指针对象的throw方法抛出的错误,可以被函数体内的try...catch代码块捕获。

function* gen(x){try {var y = yield x + 2;} catch (e){console.log(e);}return y;
}
var g = gen(1);
g.next();
g.throw('出错了');
// 出错了

出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

Thunk 函数

**传值调用:**即在进入函数体之前,就计算x + 5的值

f(x + 5)
// 传值调用时,等同于
f(6)

传名调用:

f(x + 5)
// 传名调用时,等同于
(x + 5) * 2
两种比较
  • 传值调用比较简单,但是对参数求值的时候,实际上还没用到这个参数,有可能造成性能损失。

Thunk 函数的含义

编译器的“传名调用”实现,往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。

function f(m) {return m * 2;
}
f(x + 5);
// 等同于
var thunk = function () {return x + 5;
};
function f(thunk) {return thunk() * 2;
}

JavaScript 语言是传值调用,它的 Thunk 函数含义有所不同。在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。这个单参数版本,就叫做 Thunk 函数。

// 正常版本的readFile(多参数版本)
fs.readFile(fileName, callback);
// Thunk版本的readFile(单参数版本)
var Thunk = function (fileName) {return function (callback) {return fs.readFile(fileName, callback);};
};
var readFileThunk = Thunk(fileName);
readFileThunk(callback);

thunk函数

不会

co模块

不会

相关文章:

ES6学习-Generator

Generator 种异步编程解决方案 函数会返回一个遍历器对象语法上:Generator 函数是一个状态机,封装了多个内部状态。形式上:Generator 函数是一个普通函数;有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部…...

Flowable-服务-微服务任务

目录 定义图形标记XML内容界面操作 定义 Sc 任务不是 BPMN 2.0 规范定义的官方任务,在 Flowable 中,Sc 任务是作为一种特殊的服务 任务来实现的,主要调用springcloud的微服务使用。 图形标记 由于 Sc 任务不是 BPMN 2.0 规范的“官方”任务…...

opencv03-补充-vector的操作

opencv03-补充-vector的操作 参考&#xff1a;https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html 构造方法(具体介绍看API文档) class Student {public:private:string name;};int main() {vector<int>();vector<int> v1;vector<Student&g…...

二叉树(C语言)

文章目录 1.树1.1概念1.2相关定义1.3 表示&#xff08;左孩子右兄弟&#xff09; 2.二叉树2.1概念2.2特殊的二叉树1. 满二叉树&#xff1a;2. 完全二叉树&#xff1a; 2.3二叉树的性质2.4练习 3.二叉树的存储结构1. 顺序存储2. 链式存储 4.完全二叉树的代码实现4.1堆的介绍1.堆…...

介绍下Django中的表单(forms)模块中的类forms.CharField

在Django中&#xff0c;forms.CharField() 是用于定义表单字段的类&#xff0c;它属于 Django 的表单&#xff08;forms&#xff09;模块。CharField 是用于处理字符型数据的表单字段类。它允许用户在表单中输入文本数据&#xff0c;并对该数据进行验证和处理。 forms.CharFie…...

元宇宙与数字孪生的异同?

随着数字孪生和元宇宙两个概念的爆火&#xff0c;人们对这两个“异物”也越来越好奇&#xff0c;这都是什么意思&#xff1f;听起来都差不多&#xff0c;是一样的嘛&#xff1f;本文就用最简单的话语带大家了解一下二者之间的异同。 首先来说数字孪生和元宇宙的概念 数字孪生是…...

智慧农业:科技赋能农村发展

智慧农业发展前景灿烂多彩&#xff0c;正为农业带来新的转型升级。随着科技的不断发展&#xff0c;数字化、自动化和智能化技术逐渐渗透进农业领域&#xff0c;为农民提供了更多高效便捷的农业管理方式。智慧农业通过物联网、大数据、人工智能等先进技术&#xff0c;实现对农田…...

x86架构ubuntu22下运行WILL模拟器dophin

0. 环境 i5实体机ubuntu22 1. 安装依赖 $ sudo apt install build-essential git cmake ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libevdev-dev libusb-1.0-0-dev libxrandr-dev libxi-dev libpangocairo-1.0-0 qt6-base-private-dev libblueto…...

Jvm的一些技巧

反编译字节码文件 找到对应的class文件所在的目录&#xff0c;使用javap -v -p 命令 查询运行中某个Java进程的Jvm参数 【案例】查询 MethodAreaDemo 这个类运行过程中&#xff0c;初始的元空间大小 MetaspaceSize jps 查询 Java 进程的进程ID 使用jinfo查看具体的参数&…...

8.docker仓库

文章目录 Docker仓库本地私有仓库Docker HarborDocker harbor部署访问页面创建用户下载私有仓库镜像harbor同步 Docker仓库 本地私有仓库 ##先下载 registry 镜像docker pull registry##修改配置文件&#xff0c;在 daemon.json 文件中添加私有镜像仓库地址vim /etc/dock…...

价值 1k 嵌入式面试题-计算机网络 OSI

开门见山 请讲下 OSI 各层协议的主要功能&#xff1f; 常见问题 回答不系统回答不确切无法和实际网络协议做关联对应 答题思路 OSI 代表了开放互联系统中信息从一台计算机的一个软件应用流到另一个计算机的另一个软件应用的参考模型 OSI 包含 7 层&#xff0c;每一层负责特…...

spring boot去除get post空格

1.用ControllerAdvice处理 package com.wangzs.handler;import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import org.springframewo…...

设计模式四:单例模式(Singleton)

单例模式&#xff0c;是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。 通过单例模式可以保证系统中&#xff0c;应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。 单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一…...

《水经注地图服务》发布的影像数据如何在OsgEarth中调用

OsgEarth 是一个用于OpenSceneGraph (OSG)的可扩展地形渲染工具包&#xff0c;它是一个开源、高性能、3D 图形工具包。 只需创建一个简单的 XML 文件&#xff0c;将其指向您的图像、高程和矢量数据&#xff0c;将其加载到您最喜欢的 OSG 应用程序中&#xff0c;然后开始&#…...

css滤镜:drop-shadow

一、用法 drop-shadow( offset-x offset-y blur-radius spread-radius color ) offset-x&#xff1a;此参数设置图像的水平偏移。正值将创建右侧的偏移量&#xff0c;负值将创建左侧的偏移量。offset-y&#xff1a;此参数设置图像的垂直偏移。正值创建到底部的偏移量&#xff…...

java ThreadLocal

private ThreadLocal threadLocal new ThreadLocal(); threadLocal.set(0); (int) threadLocal.get(); 上面三行代码分别是定义、赋值和取值。 介绍&#xff1a; 我们只需要实例化对象一次&#xff0c;并且也不需要知道它是被哪个线程实例化。虽然所有的线程都能访问到这个T…...

MySQL高级篇第6章(索引的数据结构)

文章目录 1、为什么使用索引2、索引及其优缺点3、InnoDB中索引的推演4、MyISAM中的索引方案5、索引的代价6、MySQL数据结构选择的合理性 1、为什么使用索引 假如给数据使用 二叉树 这样的数据结构进行存储&#xff0c;如下图所示 2、索引及其优缺点 3、InnoDB中索引的推演 4、M…...

Unity 性能优化三:动画模块、物理模块

目录 动画模块 Mecanim 模块 1.1 Animator active的数量 1.1.1 Culling Mode 1.1.2 Optimize Gameobject 1.1.3 Apply Root Motion 1.1.4 Compute Skinning 1.1.5 Animator Initialize 1.2 Legacy动画 物理模块 2.1 物理更新次数 2.1 减少不必要的Collision 2.5 A…...

延迟函数

Destory函数&#xff1a; public static void Destroy(Object obj, [DefaultValue("0.0F")] float t); Invoke函数&#xff1a; public void Invoke(string methodName, float time); 挂个空物体测试一下&#xff1a; public class DelayTest : MonoBehaviour {…...

IBM报告:2023数据泄露平均成本将达到445万美元

7月24日&#xff0c;IBM发布年度《数据泄露成本报告》显示&#xff0c;2023年全球数据泄露的平均成本达到445万美元&#xff0c;创该报告有史以来最高纪录&#xff0c;较过去3年均值增长了15&#xff05;。同一时期&#xff0c;检测安全漏洞和漏洞恶化带来的安全成本上升了42&a…...

【Python MCP服务器开发终极模板】:20年架构师亲授源码级解析与高并发优化实战

第一章&#xff1a;Python MCP服务器开发模板概览与核心设计哲学Python MCP&#xff08;Model-Controller-Protocol&#xff09;服务器开发模板是一套面向协议驱动、可插拔架构的轻量级服务框架&#xff0c;专为构建高内聚、低耦合的模型交互后端而设计。其核心不依赖于特定Web…...

ESP32-S3 开发实战:从问题排查到功能优化

1. ESP32-S3开发环境搭建与常见问题 刚拿到ESP32-S3开发板时&#xff0c;我最先遇到的就是环境配置问题。这里分享几个新手容易踩的坑&#xff1a;首先是开发工具链的选择&#xff0c;官方推荐使用ESP-IDF或Arduino IDE。我建议初学者先用Arduino IDE上手&#xff0c;因为它的库…...

手把手教你用RK3576开发板驱动RC522读卡器:一个SPI实战项目的完整配置流程

手把手教你用RK3576开发板驱动RC522读卡器&#xff1a;一个SPI实战项目的完整配置流程 在嵌入式开发领域&#xff0c;能够独立完成一个从硬件连接到软件驱动的完整项目&#xff0c;是每个开发者成长的必经之路。RK3576作为一款性能强劲的开发板&#xff0c;搭配常见的RC522读卡…...

音乐标签编辑器:让本地音乐元数据管理效率提升90%的开源工具

音乐标签编辑器&#xff1a;让本地音乐元数据管理效率提升90%的开源工具 【免费下载链接】music-tag-web 音乐标签编辑器&#xff0c;可编辑本地音乐文件的元数据&#xff08;Editable local music file metadata.&#xff09; 项目地址: https://gitcode.com/gh_mirrors/mu/…...

Qwen-Image镜像实战:基于RTX4090D,轻松实现图片问答与内容分析

Qwen-Image镜像实战&#xff1a;基于RTX4090D&#xff0c;轻松实现图片问答与内容分析 1. 引言&#xff1a;Qwen-Image镜像的核心价值 在当今多模态AI技术快速发展的背景下&#xff0c;能够同时理解图像和文本的视觉语言模型正变得越来越重要。Qwen-Image作为通义千问系列中的…...

Qwen3-ASR-1.7B实战教程:结合Punctuation Restoration模型提升标点准确率

Qwen3-ASR-1.7B实战教程&#xff1a;结合Punctuation Restoration模型提升标点准确率 语音识别技术已经相当成熟&#xff0c;但识别结果往往缺少标点符号&#xff0c;让长文本阅读变得困难。本文将教你如何将Qwen3-ASR-1.7B语音识别模型与标点恢复技术结合&#xff0c;获得既准…...

Realistic Vision V5.1效果展示:这些惊艳的人像作品都是AI生成的

Realistic Vision V5.1效果展示&#xff1a;这些惊艳的人像作品都是AI生成的 1. 当AI画师遇上专业摄影师 你有没有见过这样的AI生成人像&#xff1f;皮肤纹理清晰到能看见毛细血管&#xff0c;发丝在阳光下呈现自然的半透明质感&#xff0c;眼神光的位置精准符合物理反射规律…...

告别手动点鼠标!用Python脚本批量跑Simulink仿真,效率提升10倍

告别手动点鼠标&#xff01;用Python脚本批量跑Simulink仿真&#xff0c;效率提升10倍 在工程仿真领域&#xff0c;Simulink无疑是建模与分析的利器。但当面对参数扫描、蒙特卡洛分析或设计迭代等需要大量重复仿真的场景时&#xff0c;手动操作不仅效率低下&#xff0c;还容易…...

OpenClaw 深度研究报告:从开源框架到企业级智能体平台的演进之路

一、核心定位&#xff1a;突破"对话天花板"的执行中枢 OpenClaw&#xff08;外号"龙虾"&#xff09; 是由奥地利工程师 Peter Steinberger 于 2025 年底开发的本地优先、模型无关的 AI 智能体运行框架。其核心价值主张极为鲜明&#xff1a; “The AI that …...

实战应用:基于快马平台ai,开发并部署一个功能齐全的instagram内容下载web应用

今天想和大家分享一个实战项目&#xff1a;基于InsCode(快马)平台快速开发并部署一个功能完备的Instagram内容下载Web应用。这个项目从需求分析到上线只用了不到半天时间&#xff0c;特别适合想验证产品原型的开发者。 项目需求分析 首先明确核心功能需求&#xff1a;需要支持I…...