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 打造动态渐变按钮 详细图文教程
Apr 25 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
Jan 15 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
Oct 17 Javascript
JQuery插入DOM节点的方法
Jun 11 Javascript
关于backbone url请求中参数带有中文存入数据库是乱码的快速解决办法
Jun 13 Javascript
Js调用Java方法并互相传参的简单实例
Aug 11 Javascript
微信小程序 点击控件后选中其它反选实例详解
Feb 21 Javascript
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
Sep 20 jQuery
webpack+react+antd脚手架优化的方法
Apr 02 Javascript
学习Vue组件实例
Apr 28 Javascript
Vue移动端右滑屏幕返回上一页附源码下载
Jun 26 Javascript
详解ES6中class的实现原理
Oct 03 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
老生常谈文本文件和二进制文件的区别
2017/02/27 PHP
PHP number_format函数原理及实例解析
2020/07/14 PHP
事件冒泡是什么如何用jquery阻止事件冒泡
2013/03/20 Javascript
使用时间戳解决ie缓存的问题
2014/08/20 Javascript
javascipt:filter过滤介绍及使用
2014/09/10 Javascript
js正则表达式验证邮件地址
2015/11/12 Javascript
JavaScript代码生成PDF文件的方法
2016/02/26 Javascript
jQuery+php实时获取及响应文本框输入内容的方法
2016/05/24 Javascript
分享一个插件实现水珠自动下落效果
2016/06/01 Javascript
Jquery EasyUI Datagrid右键菜单实现方法
2016/12/30 Javascript
详解vue渲染函数render的使用
2017/12/12 Javascript
详解JavaScript 中 if / if...else...替换方式
2018/07/15 Javascript
利用Blob进行文件上传的完整步骤
2018/08/02 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
2019/07/17 Javascript
微信小程序事件 bindtap bindinput代码实例
2019/08/26 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
[50:21]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/19 DOTA
Python编程中的文件读写及相关的文件对象方法讲解
2016/01/19 Python
python 删除列表里所有空格项的方法总结
2018/04/18 Python
python遍历文件目录、批量处理同类文件
2019/08/31 Python
Python标准库:内置函数max(iterable, *[, key, default])说明
2020/04/25 Python
Python 实现国产SM3加密算法的示例代码
2020/09/21 Python
Python中qutip用法示例详解
2020/10/02 Python
python 模拟登陆163邮箱
2020/12/15 Python
selenium+headless chrome爬虫的实现示例
2021/01/08 Python
java关于string最常出现的面试题整理
2021/01/18 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
孕妇内衣和胸罩:Cake Maternity
2018/07/16 全球购物
社会保险接收函
2014/01/12 职场文书
中药学专业求职信
2014/05/31 职场文书
四年级小学生评语
2014/12/26 职场文书
龙门石窟导游词
2015/02/02 职场文书
2015年初一班主任工作总结
2015/05/13 职场文书
话题作文之生命的旋律
2019/12/17 职场文书
浅谈Java父子类加载顺序
2021/08/04 Java/Android