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 ...
随机推荐
- P1582倒水 位运算
题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒 ...
- POJ-2251 三维迷宫
题目大意:给一个三维图,可以前后左右上下6种走法,走一步1分钟,求最少时间(其实就是最短路) 分析:这里与二维迷宫是一样的,只是多了2个方向可走,BFS就行(注意到DFS的话复杂度为O(6^n)肯定会 ...
- WPF仿酷狗页面
原文:WPF仿酷狗页面 版权声明:本文为博主原创文章,如需转载请标明转载地址 http://blog.csdn.net/u013981858 https://blog.csdn.net/u013981 ...
- 3771: Triple
3771: Triple 链接 题意 n个斧头,每个斧头的价值都不同(开始时没注意到),可以取1个,2个,3个斧头组成不同的价值,求每种价值有多少种组成方案(顺序不同算一种) 分析: 生成函数 + 容 ...
- Start with PJSIP on windows
To overcome the project of HD video conferencing systerm,I should learn to use the PJSIP. I should m ...
- 剑指Offer - 九度1510 - 替换空格
剑指Offer - 九度1510 - 替换空格2013-11-29 20:53 题目描述: 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之 ...
- 《Cracking the Coding Interview》——第17章:普通题——题目7
2014-04-28 23:28 题目:给定一个数字,用英语把它读出来. 解法:ZOJ上有相反的题目.如果我要用中文读书来呢? 代码: // 17.7 Read an integer in Engli ...
- 《Cracking the Coding Interview》——第16章:线程与锁——题目5
2014-04-27 20:16 题目:假设一个类Foo有三个公有的成员方法first().second().third().请用锁的方法来控制调用行为,使得他们的执行循序总是遵从first.seco ...
- USACO Section1.5 Prime Palindromes 解题报告
pprime解题报告 —— icedream61 博客园(转载请注明出处)--------------------------------------------------------------- ...
- 19、AngularJs知识点总结 part-1
1.AngularJs AngularJs是一款JavaScript开源库,由Google维护,用来协助单一页面应用程序: AngularJs的目标是通过MVC模式增强基于浏览器的应用,使开发和测试变 ...