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 相关文章推荐
Extjs中常用表单介绍与应用
Jun 07 Javascript
使用javascript获取flash加载的百分比的实现代码
May 25 Javascript
js 控制图片大小核心讲解
Oct 09 Javascript
jQuery客户端分页实例代码
Nov 18 Javascript
jquery.validate提示错误信息位置方法
Jan 22 Javascript
Vue2 使用 Echarts 创建图表实例代码
May 18 Javascript
基于js中style.width与offsetWidth的区别(详解)
Nov 12 Javascript
vscode 开发Vue项目的方法步骤
Nov 25 Javascript
基于Vue实现的多条件筛选功能的详解(类似京东和淘宝功能)
May 07 Javascript
微信内置开发 iOS修改键盘换行为搜索的解决方案
Nov 06 Javascript
JavaScript实现简单的图片切换功能(实例代码)
Apr 10 Javascript
JS字符串和数组如何实现相互转化
Jul 02 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
PHP与已存在的Java应用程序集成
2006/10/09 PHP
在IIS上安装PHP4.0正式版
2006/10/09 PHP
从康盛产品(discuz)提取出来的模板类
2011/06/28 PHP
ThinkPHP里用U方法调用js文件实例
2015/06/18 PHP
php中str_pad()函数用法分析
2017/03/28 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
jQuery 图片切换插件(代码比较少)
2012/05/07 Javascript
如何获取select下拉框的值(option没有及有value属性)
2013/11/08 Javascript
JS实现鼠标滑过链接改变网页背景颜色的方法
2015/10/20 Javascript
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
js判断图片加载完成后获取图片实际宽高的方法
2016/02/25 Javascript
BootStrap 动态添加验证项和取消验证项的实现方法
2016/09/28 Javascript
JSON 对象未定义错误的解决方法
2016/09/29 Javascript
JavaScript中的 attribute 和 jQuery中的 attr 方法浅析
2017/01/04 Javascript
Node.js中的http请求客户端示例(request client)
2017/05/04 Javascript
浅谈在vue中用webpack打包之后运行文件的问题以及相关配置方法
2018/02/21 Javascript
Vue 之孙组件向爷组件通信的实现
2019/04/23 Javascript
JavaScript如何处理移动端拍摄图片旋转问题
2019/11/16 Javascript
Javascript实现秒表计时游戏
2020/05/27 Javascript
js回到页面指定位置的三种方式
2020/12/17 Javascript
[09:31]2016国际邀请赛中国区预选赛Yao赛后采访 答题送礼
2016/06/27 DOTA
[04:40]DOTA2-DPC中国联赛1月26日Recap集锦
2021/03/11 DOTA
python两种遍历字典(dict)的方法比较
2014/05/29 Python
Python使用bs4获取58同城城市分类的方法
2015/07/08 Python
使用Python制作微信跳一跳辅助
2018/01/31 Python
Django压缩静态文件的实现方法详析
2018/08/26 Python
sublime3之内网安装python插件Anaconda的流程
2020/11/10 Python
Python监听剪切板实现方法代码实例
2020/11/11 Python
IWOOT美国:新奇的小玩意
2018/04/27 全球购物
超市端午节活动方案
2014/01/23 职场文书
单身联谊活动方案
2014/01/29 职场文书
资源环境与城乡规划管理专业自荐书
2014/09/26 职场文书
2014年向国旗敬礼活动总结
2014/09/27 职场文书
安全守法证明
2015/06/23 职场文书
高一数学教学反思
2016/02/18 职场文书
《秋思》教学反思
2016/02/23 职场文书