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动态操作CSS
Dec 08 Javascript
JavaScript使用slice函数获取数组部分元素的方法
Apr 06 Javascript
javascript实现dom动态创建省市纵向列表菜单的方法
May 14 Javascript
深入理解JavaScript编程中的原型概念
Jun 25 Javascript
JavaScript修改作用域外变量的方法
Mar 25 Javascript
js和jQuery设置Opacity半透明 兼容IE6
May 24 Javascript
jQuery组件easyui对话框实现代码
Aug 25 Javascript
探讨AngularJs中ui.route的简单应用
Nov 16 Javascript
js实现省份下拉菜单效果
Feb 15 Javascript
vue实现一个移动端屏蔽滑动的遮罩层实例
Jun 08 Javascript
JavaScript创建对象的七种方式全面总结
Aug 21 Javascript
微信小程序wx:for循环的实例详解
Oct 07 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 join函数应用
2011/05/04 PHP
PHP文件下载实例代码浅析
2016/08/17 PHP
PHPTree――php快速生成无限级分类
2018/03/30 PHP
Laravel框架创建路由的方法详解
2019/09/04 PHP
PHP接入支付宝接口失效流程详解
2020/11/10 PHP
js类后台管理菜单类-MenuSwitch
2007/09/12 Javascript
jQuery + Flex 通过拖拽方式动态改变图片的代码
2011/08/03 Javascript
ASP.NET jQuery 实例1(在TextBox里面创建一个默认提示)
2012/01/13 Javascript
jquery实现通用版鼠标经过淡入淡出效果
2014/06/15 Javascript
介绍一个简单的JavaScript类框架
2015/06/24 Javascript
JavaScript 事件对内存和性能的影响
2017/01/22 Javascript
JS 实现随机验证码功能
2017/02/15 Javascript
基于ExtJs在页面上window再调用Window的事件处理方法
2017/07/26 Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
2017/09/11 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
bootstrap table.js动态填充单元格数据的多种方法
2019/07/18 Javascript
简单使用webpack打包文件的实现
2019/10/29 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
JavaScript实现答题评分功能页面
2020/06/24 Javascript
JS模拟实现京东快递单号查询
2020/11/30 Javascript
[43:47]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第一局
2016/03/05 DOTA
python多线程编程中的join函数使用心得
2014/09/02 Python
linux环境下python中MySQLdb模块的安装方法
2017/06/16 Python
pandas使用apply多列生成一列数据的实例
2018/11/28 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
详解python中TCP协议中的粘包问题
2019/03/22 Python
ubuntu 18.04搭建python环境(pycharm+anaconda)
2019/06/14 Python
Python实现微信翻译机器人的方法
2019/08/13 Python
关于Python3 lambda函数的深入浅出
2019/11/27 Python
Python压缩模块zipfile实现原理及用法解析
2020/08/14 Python
Microsoft Advertising美国:微软搜索广告
2019/05/01 全球购物
个人自荐书
2013/12/20 职场文书
酒店个人求职信范文
2014/01/25 职场文书
我们的节日中秋活动方案
2014/08/19 职场文书
2016大学军训心得体会
2016/01/11 职场文书
Redis配置外网可访问(redis远程连接不上)的方法
2022/12/24 Redis