简介

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. POJ :3614-Sunscreen

    传送门:http://poj.org/problem?id=3614 Sunscreen Time Limit: 1000MS Memory Limit: 65536K Total Submissio ...

  2. 15.4,redis不重启,切换RDB备份到AOF备份

      确保redis版本在2.2以上 [root@pyyuc /data ::]#redis-server -v Redis server v= sha=: malloc=jemalloc- bits= ...

  3. MAC中mongodb的连接遇到的问题及调试

    今天在MAC环境下连接mongodb,遇到了一些报错,最终调试全部搞定.在此特做记录! 首先,mongod启动失败 上面有一句话是 exception in initAndListen: 20 Att ...

  4. RSA 加解密算法详解

    RSA 为"非对称加密算法".也就是加密和解密用的密钥不同. (1)乙方生成两把密钥(公钥和私钥).公钥是公开的,任何人都可以获得,私钥则是保密的. (2)甲方获取乙方的公钥,然后 ...

  5. CSS的z-index & 绝对定位与相对定位

    1.在有些情况下,需要仔细地控制元素在网页中堆叠顺序.z-index样式属性让你能够设置元素的堆叠顺序. 堆叠元素时,z-index值较大的元素在z-index值较小的下面. 2.z-index值仅在 ...

  6. Java基本数据类型总结二

    Java 基本数据类型总结二 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据. 因此,通过 ...

  7. LC.exe已退出,代码为-1

    解决方法就是把Properties文件下的license.licx给删除,重新编译,这样就可以了.

  8. 剑指Offer - 九度1520 - 树的子结构

    剑指Offer - 九度1520 - 树的子结构2013-11-30 22:17 题目描述: 输入两颗二叉树A,B,判断B是不是A的子结构. 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每 ...

  9. CodeIgniter学习笔记二:CI中的query_builder(AR)、连贯操作

    一.开启query_builder 在application\config\database.php中添加如下代码(默认已开启): $query_builder = TRUE; 二.查询数据 //ge ...

  10. U盘的容量变小了怎么办?

    之前买了个U盘,后来给朋友装系统弄成U盘启动盘了,就发现U盘容量变少了几百兆,原来是因为做U盘启动盘的时候,U盘启动盘制作软件都是把写入U盘的PE文件隐藏了,防止用户不小心删除文件. 所以说这些空间应 ...