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 相关文章推荐
读jQuery之三(构建选择器)
Jun 11 Javascript
javascript SpiderMonkey中的函数序列化如何进行
Dec 05 Javascript
js单向链表的具体实现实例
Jun 21 Javascript
jQuery实现动画效果的简单实例
Jan 27 Javascript
jQuery Validate表单验证深入学习
Dec 18 Javascript
解析JavaScript面向对象概念中的Object类型与作用域
May 10 Javascript
详解如何在Angular中快速定位DOM元素
May 17 Javascript
js 发布订阅模式的实例讲解
Sep 10 Javascript
vue树形结构获取键值的方法示例
Jun 21 Javascript
使用异步组件优化Vue应用程序的性能
Apr 28 Javascript
解决layui 表单元素radio不显示渲染的问题
Sep 04 Javascript
小程序实现侧滑删除功能
Jun 25 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
yii操作session实例简介
2014/07/31 PHP
php简单统计在线人数的方法
2016/05/10 PHP
NiftyCube——轻松实现圆角边框
2007/02/20 Javascript
poshytip 基于jquery的 插件 主要用于显示微博人的图像和鼠标提示等
2012/10/12 Javascript
jquery ui对话框实例代码
2013/05/10 Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
2013/06/27 Javascript
javascript中的循环语句for语句深入理解
2014/04/04 Javascript
jQuery实现彩带延伸效果的网页加载条loading动画
2015/10/29 Javascript
JS实现图片高亮展示效果实例
2015/11/24 Javascript
Three.js学习之几何形状
2016/08/01 Javascript
jQuery中页面返回顶部的方法总结
2016/12/30 Javascript
Angular.JS通过指令操作DOM的方法
2017/05/10 Javascript
使用ef6创建oracle数据库的实体模型遇到的问题及解决方案
2017/11/09 Javascript
node和vue实现商城用户地址模块
2018/12/05 Javascript
图文讲解用vue-cli脚手架创建vue项目步骤
2019/02/12 Javascript
vue 在服务器端直接修改请求的接口地址
2020/12/19 Vue.js
python读取文件名称生成list的方法
2018/04/27 Python
完美解决安装完tensorflow后pip无法使用的问题
2018/06/11 Python
Python参数解析模块sys、getopt、argparse使用与对比分析
2019/04/02 Python
python实现给微信指定好友定时发送消息
2019/04/29 Python
Python中类似于jquery的pyquery库用法分析
2019/12/02 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
2020/01/02 Python
Python class的继承方法代码实例
2020/02/14 Python
基于K.image_data_format() == 'channels_first' 的理解
2020/06/29 Python
时尚的CSS3进度条效果
2012/02/22 HTML / CSS
纯CSS3实现自定义Tooltip边框涂鸦风格的教程
2014/11/05 HTML / CSS
HTML5之SVG 2D入门7—SVG元素的重用与引用
2013/01/30 HTML / CSS
Hertz荷兰:荷兰和全球租车
2018/01/07 全球购物
Skyscanner加拿大:全球旅行搜索平台
2018/11/19 全球购物
程序员机试试题汇总
2012/03/07 面试题
我的画教学反思
2014/04/28 职场文书
企业党建工作汇报材料
2014/08/19 职场文书
爱护公物演讲稿
2014/09/09 职场文书
卖房授权委托书样本
2014/10/05 职场文书
2015初中团委工作总结
2015/07/28 职场文书
SQLServer中JSON文档型数据的查询问题解决
2021/06/27 SQL Server