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中字符串的定义示例代码
Dec 19 Javascript
JavaScript的各种常见函数定义方法
Sep 16 Javascript
node.js开机自启动脚本文件
Dec 24 Javascript
jQuery实现的fixedMenu下拉菜单效果代码
Aug 24 Javascript
JavaScript操作 url 中 search 部分方法函数
Jun 15 Javascript
简单实现IONIC购物车功能
Jan 10 Javascript
JS实现针对给定时间的倒计时功能示例
Apr 11 Javascript
收藏AngularJS中最重要的核心功能
Jul 09 Javascript
cordova入门基础教程及使用中遇到的一些问题总结
Nov 14 Javascript
js正则表达式校验指定字符串的方法
Jul 23 Javascript
JS判断数组是否包含某元素实现方法汇总
Jun 24 Javascript
一起来看看Vue的核心原理剖析
Mar 24 Vue.js
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
PHP的一个完整SMTP类(解决邮件服务器需要验证时的问题)
2006/10/09 PHP
《PHP编程最快明白》第三讲:php数组
2010/11/01 PHP
destoon实现资讯信息前面调用它所属分类的方法
2014/07/15 PHP
yii用户注册表单验证实例
2015/12/26 PHP
HTML-CSS群中单选引发的“事件”
2007/03/05 Javascript
学习YUI.Ext 第七天--关于View&amp;JSONView
2007/03/10 Javascript
『JavaScript』限制Input只能输入数字实现思路及代码
2013/04/22 Javascript
jquery图片轮播插件仿支付宝2013版全屏图片幻灯片
2014/04/03 Javascript
jQuery判断复选框是否勾选的原理及示例
2014/05/21 Javascript
Jquery中扩展方法extend使用技巧
2014/08/24 Javascript
javascript实现标签切换代码示例
2016/05/22 Javascript
JavaScript实现阿拉伯数字和中文数字互相转换
2016/06/12 Javascript
jQuery EasyUI提交表单验证
2016/07/19 Javascript
JavaScript中常用的验证reg
2016/10/13 Javascript
jQuery自定义图片上传插件实例代码
2017/04/04 jQuery
vue.js图片转Base64上传图片并预览的实现方法
2018/08/02 Javascript
jQuery-ui插件sortable实现自由拖动排序
2018/12/01 jQuery
vue和better-scroll实现列表左右联动效果详解
2019/04/29 Javascript
对layer弹出框中icon数字参数的说明介绍
2019/09/04 Javascript
layui表格数据复选框回显设置方法
2019/09/13 Javascript
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
[47:20]DAC2018 4.4 淘汰赛 Optic vs Mineski 第一场
2018/04/05 DOTA
Python中处理字符串之islower()方法的使用简介
2015/05/19 Python
浅谈python实现Google翻译PDF,解决换行的问题
2018/11/28 Python
python中的decimal类型转换实例详解
2019/06/26 Python
Python制作微信好友背景墙教程(附完整代码)
2019/07/17 Python
Django框架HttpRequest对象用法实例分析
2019/11/01 Python
Python读取多列数据以及用matplotlib制作图表方法实例
2020/09/23 Python
html+css3实现的登录界面
2020/12/09 HTML / CSS
美的官方商城:Midea
2016/09/14 全球购物
英国Office鞋店德国网站:在线购买鞋子、靴子和运动鞋
2018/12/19 全球购物
华为消费者德国官方网站:HUAWEI德国
2020/11/03 全球购物
安全责任书
2015/01/29 职场文书
赞助商致辞
2015/07/30 职场文书
资深HR教你写好简历中的自我评价
2019/05/07 职场文书
Python代码,能玩30多款童年游戏!这些有几个是你玩过的
2021/04/27 Python