简介

Generator函数是ES6关于异步编程的解决方案。Generator函数能够让函数暂停执行(即交出函数的执行权),简单直白点来理解,Generator函数就是一个状态机,内部封装了多个状态(暂停执行的位置)

  • 定义:
  1. function 关键字后有一个*
  2. 函数体内部有yield表达式,表示暂停的位置,定义不同状态。
function* helloWorld(){
yield 'hello';
yield 'world';
return 'end';
}
var hw = helloWorld();
  • 调用
  1. 通过next()方法调用,返回结果形如{value:xxx, done: bool}。并在下一个yield处暂停。
  2. 当函数执行完毕(碰到return或者所有yield执行完毕),那么返回的结果value为return的值(无return 则返回undefined),done为true。
  3. 函数执行完毕后无论怎么调用next()方法,结果都是{ value: undefined, done: true }
  4. 通过next()可以传入参数进入状态机,即传入值取代yield表达式。
hw.next();
//{value:'hello',done:false}
hw.next();
//{value:'world',done:false}
hw.next();
//{value:'end',done:true}
hw.next()
//{value:'undefined',done:true}
  • yield*表达式

    yield*表达式用于在Generator函数内部调用另外一个Generator函数。

  • throw()方法

    在函数体外部抛出错误,如果内部有catch语句,那么优先内部捕获,否则为外部捕获。全局的throw命令只能够外部catch捕获

  • return()方法

    用于终结遍历Generator函数。Generator函数调用return方法后,那么返回值的done变为true,遍历终止。

    当内部有try...finally代码块时,return会推迟到finally代码块执行完后再执行。

function* numbers () {
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
}
yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }
  • 其他
  1. yield只能在Generator函数内使用
  2. Generator函数执行后会返回一个遍历器对象,通过把Generator函数赋值给对象的Symbol.iterator属性,即可使对象获得Iterator接口,可以被for...of...等遍历

应用

1. 利用Generator遍历Object的属性

function* objectEntries(obj) {
let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) {
yield [propKey, obj[propKey]];
}
} let jane = { first: 'Jane', last: 'Doe' }; for (let [key, value] of objectEntries(jane)) {
console.log(`${key}: ${value}`);
}

2. 利用yield*遍历嵌套数组

let arr = [1,2,[3,4,5,[6,7,8],9],10];

function* iterArr(arr){
for(let value of arr){
if(Array.isArray(value)){
yield* iterArr(value);
}else{
yield value;
}
}
}
for(let x of iterArr(arr)){
console.log(x);
}

3. 利用yield*中序遍历完全二叉树

//节点的构造函数

function Node(left, value, right){
this.left = left;
this.value = value;
this.right = right;
}
//完全二叉树遍历函数
function* inorder(node){
if(node){
yield* inorder(node.left);
yield node.value;
yield* inorder(node.right);
}
} //二叉树生成函数
function binaryTree(arr){
if(arr.length === 1){
return new Node(null, arr[0], null);
}
return new Node(binaryTree(arr[0]),arr[1],binaryTree(arr[2]));
} let tree = binaryTree([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]); console.log(tree); let result = [];
for (let node of inorder(tree)){
result.push(node);
}
console.log(result);

4. Generator函数的状态机实现

Generator 的确是用来实现状态机的最佳数据结构。

首先,在没有外部输入的情况,一个状态机只有内部既定的逻辑,与Generator函数一样:若未经处理,那么也是一个按照既定顺序执行的多阶段的任务队列。

通过yield 可以表示状态机的状态,利用yield来接受外界对Generator的输入,即状态机接受外部的输入参数。

然后通过内部的逻辑,将之切换到不同的下一个yield,即可实现状态机的切换。

提供一个利用Generator函数实现的简单状态机案例:

  • 状态机的状态变化如下图所示:

  • Generator函数模拟
let machine = function* (){
let states = ['初始化','状态一', '状态二', '状态三', '状态四', '退出'];
let i = 0;
let input = yield states[0];
while(true){
if(typeof input !== 'number'){
input = 0;
}
switch (i) {
case 1:
if(input <= 0) i = 3;
else if(input > 10) i = 2;
else if(input > 100) i = 4;
break; case 2:
if(input > 10) i = 4;
break;
case 3:
if(input > 10) i = 4;
else if(input < 0) i = 1;
break;
case 4:
if(input > 100) i = 1;
if(input < -100){
yield states[5];
return '状态机关闭';
}
break;
default:
i = 1;
break;
}
input = yield states[i];
}
};
machine = machine();
console.log(machine.next());
  • 函数执行结果:

参考文献

  1. ECMAScript 6入门--第16章 Generator函数的语法

Generator函数的语法的更多相关文章

  1. 15.Generator 函数的语法

    Generator 函数的语法 Generator 函数的语法 简介 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generat ...

  2. ES6的新特性(16)——Generator 函数的语法

    Generator 函数的语法 简介 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generator 函数的语法和 API,它的 ...

  3. 16.Generator函数的语法

    1.简介 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同. 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机 ...

  4. Generator 函数的语法

    简介 § ⇧ 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generator 函数的语法和 API,它的异步编程应用请看< ...

  5. 《EMCAScript6入门》读书笔记——16.Generator函数的语法

    鼠标指针移到图片上,右键,选择在“在新标签页中打开”,放大即可看到清晰文字.

  6. Generator函数异步应用

    转载请注明出处: Generator函数异步应用 上一篇文章详细的介绍了Generator函数的语法,这篇文章来说一下如何使用Generator函数来实现异步编程. 或许用Generator函数来实现 ...

  7. ECMAScript 6 学习(一)generator函数

    1.ES2017标准引入async函数,那么async函数到底是个什么函数呢? async 是一个generator函数的语法糖. 2.那么generator函数到底是什么函数ne? generato ...

  8. JavaScript中的Generator函数

    1. 简介 Generator函数时ES6提供的一种异步编程解决方案.Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机. 执行Genera ...

  9. 《ECMAScript6入门》笔记——Generator函数

    今天在看<ECMAScript6入门>的第17章——Generator函数的语法.理解起来还是有点费劲,几段代码看了很多遍.总算有点点理解了. 示例代码如下:(摘自阮一峰<ECMAS ...

随机推荐

  1. 选择排序算法Java实现

    一. 算法描述 选择排序:比如在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......第N-1 ...

  2. liteos学习文档liteos.github.io

    https://liteos.github.io该主页是华为liteos物联网操作系统的文档,里面有一章是“内核指南”,讲的是rtos的最主要的功能.可以当作liteos的入门了解,如果用rtos的使 ...

  3. I2C中24C02从地址设置

    从设备地址 首先,先看一下AT24C02的芯片资料,我们会发现AT24C02有三个地址A0,A1,A2.同时,我们会在资料的Device Address介绍发现I2C器件一共有七位地址码,还有一位是读 ...

  4. Dragger 2遇到的坑 Dragger2详解 Dragger2学习最好的资料

    我是曹新雨,我为自己代言.现在的菜鸟,3年以后我就是大神.为自己加油.微信:aycaoxinyu Dragger2是什么,我就不再说了.资料一堆,而且里面的注解什么意思,我推荐两篇文章,这两篇都是我精 ...

  5. 【转】灰色在PPT中的运用

    一.作为背景   灰色作为背景能够有效烘托其他元素,特别是与白/黑色渐变,效果更好.   1.黑灰渐变,科技感十足 2.纯灰:简单清晰 http://www.behance.net/gallery/N ...

  6. jmeter 运行脚本报错 java.net.BindException: Address already in use

    在win下跑jmeter时,在聚合报告中出现错误.打开日志文件(前提是将日志写入了指定文件) 发现报错的原因为:java.net.BindException: Address already in u ...

  7. mysql用root账户建立用户和赋予权限

    1.创建用户 create user guest_test@localhost identified by "root";-- 创建名为guest_test的用户 2.赋予权限 - ...

  8. 常用模块(shutil copy、压缩、解压)

    作用与功能 主要用于文件的copy,压缩,解压 导入shuitl模块: import shutil copy方法 1 1.shutil.copyfileobj()  打开file1,并copy写入fi ...

  9. C# http Post与Get方法控制继电器

    ---恢复内容开始--- using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  10. Spring 笔记(一)概念梳理

    概念 预备知识 1. POJO POJO是Plain Old Java Object的缩写,是软件开发大师Martin Fowler提出的一个概念,指的是一个普通Java类.也就说,你随便编写一个Ja ...