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 Tab选项卡效果代码改进版
Apr 01 Javascript
从零开始学习jQuery (二) 万能的选择器
Oct 01 Javascript
JavaScript分页功能的实现方法
Apr 25 Javascript
jQuery实现输入框邮箱内容自动补全与上下翻动显示效果【附demo源码下载】
Sep 20 Javascript
react-native 圆弧拖动进度条实现的示例代码
Apr 12 Javascript
vue-cli 3.x 修改dist路径的方法
Sep 19 Javascript
Vue 第三方字体图标引入 Font Awesome的方法
Sep 28 Javascript
详解js常用分割取字符串的方法
May 15 Javascript
在Vue项目中用fullcalendar制作日程表的示例代码
Aug 04 Javascript
微信小程序 组件的外部样式externalClasses使用详解
Sep 06 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
Feb 17 Javascript
vant时间控件使用方法详解
Dec 24 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动画电影《黑暗正义联盟》曝预告 5月5日上线数字平台
2020/04/09 欧美动漫
一个查看session内容的函数
2006/10/09 PHP
php格式化时间戳显示友好的时间实现思路及代码
2014/10/23 PHP
浅析php创建者模式
2014/11/25 PHP
PHP信号量基本用法实例详解
2016/02/12 PHP
Zend Framework动作助手Json用法实例分析
2016/03/05 PHP
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二
2011/12/31 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
jquery实现metro效果示例代码
2013/09/06 Javascript
css样式标签和js语法属性区别
2013/11/06 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
2016/11/23 Javascript
详解vue 中使用 AJAX获取数据的方法
2017/01/18 Javascript
从零学习node.js之express入门(六)
2017/02/25 Javascript
Vue.js实现的计算器功能完整示例
2018/07/11 Javascript
vue-cli项目无法用本机IP访问的解决方法
2018/09/20 Javascript
关于AOP在JS中的实现与应用详解
2019/05/06 Javascript
从零使用TypeScript开发项目打包发布到npm
2020/02/14 Javascript
JavaScript定时器使用方法详解
2020/03/26 Javascript
Python中使用scapy模拟数据包实现arp攻击、dns放大攻击例子
2014/10/23 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
Python实现的径向基(RBF)神经网络示例
2018/02/06 Python
在VS Code上搭建Python开发环境的方法
2018/04/06 Python
python爬取内容存入Excel实例
2019/02/20 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
Python中qutip用法示例详解
2020/10/02 Python
澳大利亚排名第一的儿童在线玩具商店:Toy Galaxy
2018/10/06 全球购物
加拿大大码女装购物网站:Penningtons
2020/12/26 全球购物
运动会表扬稿大全
2014/01/16 职场文书
《守株待兔》教学反思
2014/03/01 职场文书
酒店仓管员岗位职责
2014/04/28 职场文书
幼儿园迎国庆65周年活动策划方案
2014/09/16 职场文书
幼儿园感恩节活动方案2014
2014/10/11 职场文书
购房个人委托书范本
2014/10/11 职场文书
分析设计模式之模板方法Java实现
2021/06/23 Java/Android
我的收音机情缘
2022/04/05 无线电
悬疑名作《朋友游戏》动画无字ED宣传片 新角色公开
2022/04/13 日漫