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实现检测浏览器及版本的脚本代码
Jan 22 Javascript
javascript模仿msgbox提示效果代码
Jun 10 Javascript
jQuery 判断页面元素是否存在的代码
Aug 14 Javascript
Select标签下拉列表二级联动级联实例代码
Feb 07 Javascript
jQuery实现的数值范围range2dslider选取插件特效多款代码分享
Aug 27 Javascript
原生js页面滚动延迟加载图片
Dec 20 Javascript
js实现select二级联动下拉菜单
Apr 17 Javascript
微信小程序 开发指南详解
Sep 27 Javascript
对javascript继承的理解
Oct 11 Javascript
Angular4 中常用的指令入门总结
Jun 12 Javascript
jQuery动画_动力节点节点Java学院整理
Jul 04 jQuery
Element图表初始大小及窗口自适应实现
Jul 10 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字符串截取函数用法分析
2014/11/25 PHP
php 流程控制switch的简单实例
2016/06/07 PHP
thinkphp实现分页显示功能
2016/12/03 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
PHP高并发和大流量解决方案整理
2021/03/09 PHP
页面使用密码保护代码
2013/04/10 Javascript
详细介绍8款超实用JavaScript框架
2013/10/25 Javascript
点击弹出层效果&amp;弹出窗口后网页背景变暗效果的实现代码
2014/02/10 Javascript
jquery队列函数用法实例
2014/12/16 Javascript
深入理解JavaScript系列(36):设计模式之中介者模式详解
2015/03/04 Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
2016/09/01 Javascript
jquery根据td给相同tr下其他td赋值的实现方法
2016/10/05 Javascript
Vue.js 2.0 移动端拍照压缩图片预览及上传实例
2017/04/27 Javascript
给vue项目添加ESLint的详细步骤
2017/09/29 Javascript
微信小程序使用map组件实现路线规划功能示例
2019/01/22 Javascript
JS实现电脑虚拟键盘打字测试
2020/06/24 Javascript
[03:09]显微镜下的DOTA2第一期——带你走进华丽的DOTA2世界
2014/06/20 DOTA
Python时间戳与时间字符串互相转换实例代码
2013/11/28 Python
Python三级目录展示的实现方法
2016/09/28 Python
利用python获取当前日期前后N天或N月日期的方法示例
2017/07/30 Python
Python selenium实现微博自动登录的示例代码
2018/05/16 Python
解决pycharm无法调用pip安装的包问题
2018/05/18 Python
Flask框架配置与调试操作示例
2018/07/23 Python
Python实现从SQL型数据库读写dataframe型数据的方法【基于pandas】
2019/03/18 Python
python实现静态web服务器
2019/09/03 Python
python numpy库np.percentile用法说明
2020/06/08 Python
利用纯CSS3实现文字向右循环闪过效果实例(可用于移动端)
2017/06/15 HTML / CSS
浅谈pc和移动端的响应式的使用
2019/01/03 HTML / CSS
html5简介_动力节点Java学院整理
2017/07/07 HTML / CSS
Html5获取高德地图定位天气的方法
2019/12/26 HTML / CSS
无谷物狗粮:Pooch & Mutt
2018/05/23 全球购物
《藏戏》教学反思
2014/02/11 职场文书
国际经济贸易专业自荐信
2014/06/13 职场文书
幼儿园健康教育方案
2014/06/14 职场文书
新郎父亲婚礼致辞
2015/07/27 职场文书
深入浅出讲解Java8函数式编程
2022/01/18 Java/Android