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清空file文件域的解决方案
Apr 12 Javascript
js 单击式的下拉菜单效果实例
Aug 13 Javascript
基于jquery的网站幻灯片切换效果焦点图代码
Sep 15 Javascript
ExtJS[Desktop]实现图标换行示例代码
Nov 17 Javascript
js利用prototype调用Array的slice方法示例
Jun 09 Javascript
AJAX实现瀑布流触发分页与分页触发瀑布流的方法
May 23 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
Jun 20 Javascript
JS实现动画兼容性的transition和transform实例分析
Dec 13 Javascript
mui上拉加载功能实例详解
Apr 13 Javascript
Flask中获取小程序Request数据的两种方法
May 12 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
Jun 19 Javascript
Vue实现简单的留言板
Oct 23 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缓存类代码(附详细说明)
2011/06/09 PHP
laravel migrate初学常见错误的解决方法
2017/10/11 PHP
InnerHtml和InnerText的区别分析
2009/03/13 Javascript
jquery 表单下所有元素的隐藏
2009/07/25 Javascript
Jquery判断IE6等浏览器的代码
2011/04/05 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
JS+CSS实现实用的单击输入框弹出选择框的方法
2015/02/28 Javascript
JS判断当前页面是否在微信浏览器打开的方法
2015/12/08 Javascript
在Linux系统中搭建Node.js开发环境的简单步骤讲解
2016/01/26 Javascript
js匿名函数作为函数参数详解
2016/06/01 Javascript
JavaScript直播评论发弹幕切图功能点集合效果代码
2016/06/26 Javascript
Javascript表单特效之十大常用原理性样例代码大总结
2016/07/12 Javascript
vue2.0开发实践总结之疑难篇
2016/12/07 Javascript
微信小程序实现全局搜索代码高亮的示例
2018/03/30 Javascript
js 根据对象数组中的属性进行排序实现代码
2019/09/12 Javascript
Python实现调度算法代码详解
2017/12/01 Python
Python Django框架实现应用添加logging日志操作示例
2019/05/17 Python
使用python实现回文数的四种方法小结
2019/11/24 Python
Python面向对象原理与基础语法详解
2020/01/02 Python
python实现word文档批量转成自定义格式的excel文档的思路及实例代码
2020/02/21 Python
python pyqtgraph 保存图片到本地的实例
2020/03/14 Python
浅谈TensorFlow中读取图像数据的三种方式
2020/06/30 Python
Python Charles抓包配置实现流程图解
2020/09/29 Python
接口自动化多层嵌套json数据处理代码实例
2020/11/20 Python
css3使网页、图片变成灰色兼容大多数浏览器
2014/07/02 HTML / CSS
奥地利度假券的专家:we-are.travel
2019/04/10 全球购物
阿迪达斯印尼官方网站:adidas印尼
2020/02/10 全球购物
Java里面如何把一个Array数组转换成Collection, List
2013/07/26 面试题
2014学生会工作总结报告
2014/12/02 职场文书
数学考试作弊检讨书300字
2015/02/16 职场文书
大学三好学生主要事迹范文
2015/11/03 职场文书
创业计划书之餐饮馄饨店
2019/07/18 职场文书
MySQL Router的安装部署
2021/04/24 MySQL
海康机器人重磅发布全新算法开发平台VM4.2
2022/04/21 数码科技
如何利用python创作字符画
2022/06/25 Python