Generator函数的语法
简介
Generator函数是ES6关于异步编程的解决方案。Generator函数能够让函数暂停执行(即交出函数的执行权),简单直白点来理解,Generator函数就是一个状态机,内部封装了多个状态(暂停执行的位置)。
- 定义:
- function 关键字后有一个
*号 - 函数体内部有
yield表达式,表示暂停的位置,定义不同状态。
function* helloWorld(){
yield 'hello';
yield 'world';
return 'end';
}
var hw = helloWorld();
- 调用
- 通过next()方法调用,返回结果形如
{value:xxx, done: bool}。并在下一个yield处暂停。 - 当函数执行完毕(碰到return或者所有yield执行完毕),那么返回的结果value为return的值(无return 则返回undefined),done为true。
- 函数执行完毕后无论怎么调用next()方法,结果都是
{ value: undefined, done: true }。 - 通过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 }
- 其他
- yield只能在Generator函数内使用
- 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());
- 函数执行结果:

参考文献
Generator函数的语法的更多相关文章
- 15.Generator 函数的语法
Generator 函数的语法 Generator 函数的语法 简介 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generat ...
- ES6的新特性(16)——Generator 函数的语法
Generator 函数的语法 简介 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generator 函数的语法和 API,它的 ...
- 16.Generator函数的语法
1.简介 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同. 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机 ...
- Generator 函数的语法
简介 § ⇧ 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同.本章详细介绍 Generator 函数的语法和 API,它的异步编程应用请看< ...
- 《EMCAScript6入门》读书笔记——16.Generator函数的语法
鼠标指针移到图片上,右键,选择在“在新标签页中打开”,放大即可看到清晰文字.
- Generator函数异步应用
转载请注明出处: Generator函数异步应用 上一篇文章详细的介绍了Generator函数的语法,这篇文章来说一下如何使用Generator函数来实现异步编程. 或许用Generator函数来实现 ...
- ECMAScript 6 学习(一)generator函数
1.ES2017标准引入async函数,那么async函数到底是个什么函数呢? async 是一个generator函数的语法糖. 2.那么generator函数到底是什么函数ne? generato ...
- JavaScript中的Generator函数
1. 简介 Generator函数时ES6提供的一种异步编程解决方案.Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机. 执行Genera ...
- 《ECMAScript6入门》笔记——Generator函数
今天在看<ECMAScript6入门>的第17章——Generator函数的语法.理解起来还是有点费劲,几段代码看了很多遍.总算有点点理解了. 示例代码如下:(摘自阮一峰<ECMAS ...
随机推荐
- P2158 [SDOI2008] (欧拉函数
题目描述 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图 ...
- 牛客暑假多校第二场J-farm
一.题意 White Rabbit has a rectangular farmland of n*m. In each of the grid there is a kind of plant. T ...
- PHP.24-TP框架商城应用实例-后台1-添加商品功能、钩子函数、在线编辑器、过滤XSS、上传图片并生成缩略图
添加商品功能 1.创建商品控制器[C] /www.test.com/shop/Admin/Controller/GoodsController.class.php <?php namespace ...
- cocos2d-x 3.0 Node与Node层级结构
节点解释: 节点是场景图的基本元素.场景图的基本元素必须是节点对象或者是节点对象的子类. 其中主要可以看到Layer.MenuItem.Scene.Sprite.TMXTiledMap(解析and渲染 ...
- CSS3裁剪与遮罩解析
一.用途 CSS3裁剪与遮罩(Clipping and Masking)用来隐藏元素的一部分而显示另一部分 二.区别 CSS3裁剪与遮罩(Clipping and Masking)用来隐藏元素的一部分 ...
- centos使用--软件启动关闭等操作的命令
关于centos服务的命令经常会遇到这几种 service systemctl /etc/init.d/ 1 service和/etc/init.d/ service是一个脚本命令,分析service ...
- vim 简单命令
(1)查找结果全部单独显示 命令: :lvimgrep /pattern/ % | lopen (2)设置文本高亮 命令: :colorscheme evening 把 ":colorsch ...
- 《Cracking the Coding Interview》——第9章:递归和动态规划——题目9
2014-03-20 04:08 题目:八皇后问题. 解法:DFS解决. 代码: // 9.9 Eight-Queen Problem, need I say more? #include <c ...
- USACO Section2.2 Runaround Numbers 解题报告 【icedream61】
runround解题报告---------------------------------------------------------------------------------------- ...
- 最干净的pyinstaller打包成exe应用程序方法
在anaconda环境下进行pyinstaller打包后,程序非常大,70行代码打包后有280MB,这是因为会将conda环境携带的库都打包进去导致的.为了获得更纯净的包环境,我们需要安装纯pytho ...