ES6新特性三: Generator(生成器)函数详解


Posted in Javascript onApril 21, 2017

本文实例讲述了ES6新特性三: Generator(生成器)函数。分享给大家供大家参考,具体如下:

1. 简介

① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改变。

② 写法:

function* f() {}

③ 作用:就是可以完全控制函数的内部状态的变化,依次遍历这些状态。

④ 运行过程:当调用Generator函数的时候,该函数并不执行,而是返回一个遍历器(可以理解成暂停执行)。通过调用next()开始执行,遇到yield停止执行,返回一个value属性值为当前yield语句的值,done属性为false的对象,循环调用next(),一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。

示例:

function* helloWorldGenerator() {
 yield 'hello';
 yield 'world';
 return 'ending';
}
var hw = helloWorldGenerator();//第一次调用该方法不会执行,仅返回一个遍历器。
var a = hw.next();
while(!a.done){ //当执行到return 时,a.done=true,终止循环
 console.log(a.value+','+a.done);
 a = hw.next();
}
console.log(a.value+','+a.done);

结果:

hello,false
world,false
ending,true

2. next() 的参数

① 我们要知道是next()返回一个对象,yield语句本身是没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值

function* f() {
 for(var i=0; true; i++) {
  var reset = yield i;
  console.log(reset); //打印reset,验证yield语句是没有返回值的
  if(reset) { i = -1; }
 }
}
var g = f();
console.log(g.next()) // { value: 0, done: false }
console.log(g.next())// { value: 1, done: false }
console.log(g.next(true)) // { value: 0, done: false }

结果:

{ value: 0, done: false }
undefined
{ value: 1, done: false }
true
{ value: 0, done: false }

通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。

②由于next方法的参数表示上一个yield语句的返回值,所以第一次使用next方法时,不能带有参数。V8引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。

function* foo(x) {
 var y = 2 * (yield (x + 1));
 var z = yield (y / 3);
 return (x + y + z);
}
var it = foo(5);
console.log(it.next(3))// { value:6, done:false }
console.log(it.next(12))// { value:8, done:false }
console.log(it.next(13))// { value:42, done:true }

3. for-of 遍历generator

for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法,

一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象

function *foo() {
 yield 1;
 yield 2;
 yield 3;
 yield 4;
 yield 5;
 return 6;
}
for (let v of foo()) {
 console.log(v);
}
// 1 2 3 4 5

4. yield* 语句

① 如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。

let a = (function* () {
 yield 'Hello!';
 yield 'Bye!';
}());
let b = (function* () {
 yield 'Greetings!';
 yield* a;
 yield 'Ok, bye.';
}());
for(let value of b) {
 console.log(value);
}

结果:

Greetings!
Hello!
Bye!
Ok, bye.

② yield命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器。

function* gen(){
 yield* ["a", "b", "c"];
}
gen().next() // { value:"a", done:false }

遍历嵌套数组:

function* iterTree(tree) {
 if (Array.isArray(tree)) {
 for(let i=0; i < tree.length; i++) {
  yield* iterTree(tree[i]);
 }
 } else {
 yield tree;
 }
}
const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
for(let x of iterTree(tree)) {
 console.log(x);
}// a b c d e

希望本文所述对大家ECMAScript程序设计有所帮助。

Javascript 相关文章推荐
深入理解javascript的执行顺序
Apr 04 Javascript
js 操作符汇总
Nov 08 Javascript
JavaScript中校验银行卡号的实现代码
Dec 19 Javascript
Javascript 使用ajax与C#获取文件大小实例详解
Jan 13 Javascript
AngularJS之ionic 框架下实现 Localstorage本地存储
Apr 22 Javascript
微信小程序request出现400的问题解决办法
May 23 Javascript
js移动端图片压缩上传功能
Aug 18 Javascript
web前端开发中常见的多列布局解决方案整理(一定要看)
Oct 15 Javascript
Angular实现双向折叠列表组件的示例代码
Nov 21 Javascript
在vue中添加Echarts图表的基本使用教程
Nov 22 Javascript
JS中call和apply函数用法实例分析
Jun 20 Javascript
React中获取数据的3种方法及优缺点
Feb 18 Javascript
Cookies 和 Session的详解及区别
Apr 21 #Javascript
node.js(express)中使用Jcrop进行图片剪切上传功能
Apr 21 #Javascript
原生javascript实现分页效果
Apr 21 #Javascript
微信小程序 跳转方式总结
Apr 20 #Javascript
微信小程序 setData的使用方法详解
Apr 20 #Javascript
ES6新特性二:Iterator(遍历器)和for-of循环详解
Apr 20 #Javascript
微信小程序中form 表单提交和取值实例详解
Apr 20 #Javascript
You might like
mysql_num_rows VS COUNT 效率问题分析
2011/04/23 PHP
php新浪微博登录接口用法实例
2014/12/23 PHP
PHP PDOStatement::nextRowset讲解
2019/02/01 PHP
laravel框架 laravel-admin上传图片到oss的方法
2019/10/13 PHP
JS获取scrollHeight问题想到的标准问题
2007/05/27 Javascript
通过jQuery打造支持汉字,拼音,英文快速定位查询的超级select插件
2010/06/18 Javascript
Js操作Select大全(取值、设置选中等等)
2013/10/29 Javascript
javascript字母大小写转换的4个函数详解
2014/05/09 Javascript
多个$(document).ready()的执行顺序实例分析
2014/07/26 Javascript
JavaScript前端图片加载管理器imagepool使用详解
2014/12/29 Javascript
快速掌握Node.js模块封装及使用
2016/03/21 Javascript
基于JS如何实现类似QQ好友头像hover时显示资料卡的效果(推荐)
2016/06/09 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
vue解决使用webpack打包后keep-alive不生效的方法
2018/09/01 Javascript
使用Node.js实现一个多人游戏服务器引擎
2019/03/13 Javascript
Node.js + express实现上传大文件的方法分析【图片、文本文件】
2019/03/14 Javascript
Javascript ParentNode和ChildNode接口原理解析
2020/03/16 Javascript
js实现带箭头的进度流程
2020/03/26 Javascript
JavaScript 正则应用详解【模式、欲查、反向引用等】
2020/05/13 Javascript
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
[01:07:22]2014 DOTA2华西杯精英邀请赛 5 24 DK VS VG加赛
2014/05/26 DOTA
[01:29:46]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第二局
2016/02/27 DOTA
[49:13]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第一局
2016/02/27 DOTA
Python编程中装饰器的使用示例解析
2016/06/20 Python
Python实现定制自动化业务流量报表周报功能【XlsxWriter模块】
2019/03/11 Python
Python占用的内存优化教程
2019/07/28 Python
Django之模板层的实现代码
2019/09/09 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
结束运行python的方法
2020/06/16 Python
The Outnet亚太地区:折扣设计师时装店
2019/12/05 全球购物
Ticketmaster意大利:音乐会、节日、艺术和剧院的官方门票
2019/12/23 全球购物
地球一小时宣传标语
2014/06/24 职场文书
商务经理岗位职责
2014/08/03 职场文书
在HTML5 localStorage中存储对象的示例代码
2021/04/21 Javascript
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang
OpenCV-Python实现怀旧滤镜与连环画滤镜
2021/06/09 Python