简介

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. idea debug启动项目慢或者启动不了

    使用debug无法启动项目但是使用run就可以启动程序,而且启动比以前的debug模式快的多 原因: 启动不了的原因是在项目中的方法上打了断点,导致项目无法继续编译 取消方法断点就可以了 在idea官 ...

  2. [CodeForces - 296D]Greg and Graph(floyd)

    Description 题意:给定一个有向图,一共有N个点,给邻接矩阵.依次去掉N个节点,每一次去掉一个节点的同时,将其直接与当前节点相连的边和当前节点连出的边都需要去除,输出N个数,表示去掉当前节点 ...

  3. 笔记-pyrhon-lib-requests

    笔记-pyrhon-lib-requests 1.      简介 Requests is the only Non-GMO HTTP library for Python, safe for hum ...

  4. toolbar menu 字体颜色和大小

    Toolbar菜单中menu当中我们大多数都使用图片来按钮,可是有些时候我们也会直接使用文字,文字的颜色如何修改呢. 其实很简单,我们只要修改styles.xml文件中,添加一句 <item n ...

  5. hive原理

    什么是Hive Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能. Hive架构图 Jobtracker是hadoop1.x中的组件,它的 ...

  6. Java-JNA使用心得

    自上个月20号,历时整整一个月,终于找到工作入职了. 然后这段时间一直看公司的框架还有业务方面的东西.其实由于给分配了一个研究Java调用C语言接口的问题,导致框架业务方面的东西还不熟,然后现在手上又 ...

  7. ElasticSearch学习笔记(五)-- 排序、分页与遍历

    1. 相关性算分 这样能够查询到不同分片上的文档的准确算分,默认分片为5 2. sorting-doc-values-fielddata 3. 分页与遍历

  8. ubuntu上通用解压方式

    ubuntu上通用解压方式 tar xvf *.bin.tar.gz,gz,tar.tgz

  9. 用scrapy数据抓取实践

    本文来自网易云社区 作者:沈高峰 数据分析中需要用到的不少数据都是需要进行抓取的,并且需要对抓取的数据进行解析之后存入数据库.scrapy是一个强大的爬虫框架,本文简单介绍下使用scrapy进行垂直抓 ...

  10. IIS 部署网站--浏览--“该页无法显示”

    解决办法: 打开IIS管理器--web站点(网站)--右键点击对应的站点--属性--主目录--执行权限改为(脚本和和执行文件) 点击“应用”--确定. 重启一下站点,OK.