简介

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. python 函数 闭包 (节省内存空间 html 获取网页的源码)

    #闭包:嵌套函数,内部函数调用外部函数的变量 # def outer(): # a = 1 # def inner(): # print(a) # inner() # outer() def oute ...

  2. [Link-Cut-Tree][BZOJ2002]弹飞绵羊

    题面 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上\(n\)个 ...

  3. java 值传递 和 引用传递

    参考:(http://www.cnblogs.com/woshimrf/p/5263018.html) 参考:(http://www.cnblogs.com/binyue/p/3862276.html ...

  4. Eclipse 工作空间(Workspace)---Eclipse教程第07课

    Eclipse 工作空间(Workspace) eclipse 工作空间包含以下资源: 项目 文件 文件夹 项目启动时一般可以设置工作空间,你可以将其设置为默认工作空间,下次启动后无需再配置: 工作空 ...

  5. Active Directory 域服务 (AD DS) 虚拟化

    TechNet 库 Windows Server Windows Server 2012 R2 和 Windows Server 2012 服务器角色和技术 Active Directory Acti ...

  6. 21、AngularJs知识点总结 part-3

    1.选择框select 在 AngularJS 中我们可以使用 ng-option 指令来创建一个下拉列表,列表项通过对象和数组循环输出,也可以使用ng-repeat 指令来创建下拉列表: 区别:ng ...

  7. jeakins忘记密码时的处理(简单粗暴)

    1.打开config文件(通过ps -elf | grep jenkins查看JENKINS_HOME目录,然后在目录下查找config.xml文件) 2.修改<useSecurity>t ...

  8. HTML--留

    1.html图像   <p> 这是个图像<img src=“\路径\”  alt=“图像不显示不出来时代替图片” width=“1” height=“1” >   </p ...

  9. python multiprocessing.Pool 中map、map_async、apply、apply_async的区别

    multiprocessing是python的多进程库,multiprocessing.dummy则是多线程的版本,使用都一样. 其中都有pool池的概念,进程池/线程池有共同的方法,其中方法对比如下 ...

  10. mysql Access denied for user 'root'@'localhost'问题解决

    问题描述: 系统安装mysql的过程中,没有提示配置用户名和密码相关的信息,安装完毕后,登录报错. 表现现象为: mysql -u root -p [输入root密码] 界面提示: ERROR 169 ...