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 相关文章推荐
基于逻辑运算的简单权限系统(实现) JS 版
Mar 24 Javascript
Prototype Selector对象学习
Jul 23 Javascript
Javascript中Array用法实例分析
Jun 13 Javascript
自己动手写的jquery分页控件(非常简单实用)
Oct 28 Javascript
基于jQuery实现火焰灯效果导航菜单
Jan 04 Javascript
vue双向数据绑定原理探究(附demo)
Jan 17 Javascript
bootstrap模态框示例代码分享
May 17 Javascript
js获取一组日期中最近连续的天数
May 25 Javascript
详解vue 配合vue-resource调用接口获取数据
Jun 22 Javascript
Angular利用trackBy提升性能的方法
Jan 26 Javascript
vue-cli 3.0 版本与3.0以下版本在搭建项目时的区别详解
Dec 11 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
Mar 05 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
曾在DC漫画界反派角色扮演的演员,谁才是你心目中的小丑之王?
2020/04/09 欧美动漫
解析获取优酷视频真实下载地址的PHP源代码
2013/06/26 PHP
php判断输入是否是纯数字,英文,汉字的方法
2015/03/05 PHP
PHP查找与搜索数组元素方法总结
2015/06/12 PHP
Symfony2联合查询实现方法
2016/03/18 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
js 数组操作代码集锦
2009/04/28 Javascript
过虑特殊字符输入的js代码
2010/08/05 Javascript
Jquery中使用setInterval和setTimeout的方法
2013/04/08 Javascript
js简单实现HTML标签Select联动带跳转
2013/10/23 Javascript
简述Jquery与DOM对象
2015/07/10 Javascript
js处理层级数据结构的方法小结
2017/01/17 Javascript
js时间查询插件使用详解
2017/04/07 Javascript
Javascript实现信息滚动效果
2017/05/18 Javascript
mescroll.js上拉加载下拉刷新组件使用详解
2017/11/13 Javascript
javascript字体颜色控件的开发 JS实现字体控制
2017/11/27 Javascript
微信小程序实现action-sheet弹出底部菜单功能【附源码下载】
2017/12/09 Javascript
vue中@change兼容问题详解
2019/10/25 Javascript
JavaScript 浏览器对象模型BOM原理与常见用法实例分析
2019/12/16 Javascript
js Math数学简单使用操作示例
2020/03/13 Javascript
JavaScript中条件语句的优化技巧总结
2020/12/04 Javascript
[49:27]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第一场
2018/04/05 DOTA
下载给定网页上图片的方法
2014/02/18 Python
Python基于pycrypto实现的AES加密和解密算法示例
2018/04/10 Python
Python增强赋值和共享引用注意事项小结
2019/05/28 Python
详解PyQt5信号与槽的几种高级玩法
2020/03/24 Python
Django自定义列表 models字段显示方式
2020/04/03 Python
python uuid生成唯一id或str的最简单案例
2021/01/13 Python
红头文件任命书范本
2014/06/05 职场文书
低碳环保演讲稿
2014/08/28 职场文书
后进基层党组织整改方案
2014/10/25 职场文书
实习推荐信格式模板
2015/03/27 职场文书
防卫过当辩护词
2015/05/21 职场文书
《实心球》教学反思
2016/02/23 职场文书
Python Django搭建文件下载服务器的实现
2021/05/10 Python