1.简介

    Generator函数是一个函数的内部状态的遍历器(也就是说,Generator函数是一个状态机)。
形式上,Generator函数是一个普通函数,但是有两个特征。
  • function命令与函数名之间有一个星号*;
  • 函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态。
    function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
let hw = helloWorldGenerator();
console.log(hw.next());// { value: 'hello', done: false }
console.log(hw.next());// { value: 'world', done: false }
console.log(hw.next());// { value: 'ending', done: true }
console.log(hw.next());// { value: undefined, done: true }

总结:

  • 调用Generator函数,返回一个部署了Iterator接口的遍历器对象,用来操作内部指针。
  • 以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
  • value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

2.next方法的参数

yield语句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
    function* f() {
for(let i=0; true; i++) {
var reset = yield i;
if(reset) { i = -1; }
}
}
let 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 }
上面代码先定义了一个可以无限运行的Generator函数f,如果next方法没有参数,每次运行到yield语句,变量reset的值总是undefined。
当next方法带一个参数true时,当前的变量reset就被重置为这个参数(即true),因此i会等于-1,下一轮循环就会从-1开始递增。

3.for...of循环

for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法。
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
}
上面代码使用for...of循环,依次显示5个yield语句的值。
注意:
一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for...of循环之中。
下面是一个利用generator函数和for...of循环,实现斐波那契数列的例子。
function* fibonacci() {
let [prev, curr] = [0, 1];
for (;;) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
if (n > 1000) break;
console.log(n);
}
从上面代码可见,使用for...of语句时不需要使用next方法。

4.throw方法

Generator 函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。
    function* gen(x){
try {
var y = yield x + 2;
} catch (e){
console.log(e);
}
return y;
}
let g = gen(1);
g.next();
g.throw('出错了');// 出错了
上面代码的最后一行,Generator 函数体外,使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。
这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

5.yield*语句

如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。
其实yield关键字就是以一种更直观、便捷的方式让我们创建用于遍历有限序列集合的迭代器,而yield则用于将生成器函数的代码切片作为有限序列集合的元素(元素的类型为指令+数据,而不仅仅是数据而已)。下面我们一起看看yield关键字是怎样对代码切片的吧!
定义生成器函数
function *enumerable(msg){
document.write(msg)
var msg1 = yield msg + ' after '
document.write(msg1)
var msg2 = yield msg1 + ' after'
document.write(msg2 + ' over')
}
//上述代码最终会被解析为下面的代码: var enumerable = function(msg){
var state = -1
return {
next: function(val){
switch(++state){
case 0:
document.write(msg + ' after')
break
case 1:
var msg1 = val
document.write(msg1 + ' after')
break
case 2:
var msg2 = val
document.write(msg2 + ' over')
break
}
}
}
}

6.作为对象属性的Generator函数

如果一个对象的属性是Generator函数,可以简写成下面的形式。
    let obj1 = {
* myGeneratorMethod() { }
};
//上面代码中,myGeneratorMethod属性前面有一个星号,表示这个属性是一个Generator函数。
//它的完整形式如下,与上面的写法是等价的。
let obj2 = {
myGeneratorMethod: function* () { }
};

此篇终,待续……

es6笔记6^_^generator的更多相关文章

  1. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  2. ES6笔记系列

    ES6,即ECMAScript 6.0,ES6的第一个版本是在2015年发布的,所以又称作ECMAScript 2015 如今距ES6发布已经一年多的时间,这时候才去学,作为一个JSer,羞愧羞愧,还 ...

  3. ES6笔记(1) -- 环境配置支持

    系列文章 -- ES6笔记系列 虽然ES6已经发布一年多了,但在各大浏览器之中的支持度还不是很理想,在这查看ES6新特性支持度 Chrome的最新版本浏览器大部分已经支持,在Node.js环境上支持度 ...

  4. ES6笔记(2)-- let的块级作用域

    系列文章 -- ES6笔记系列 一.函数级作用域 我们都知道,在ES6以前,JS只有函数级作用域,没有块级作用域这个概念 没有块级作用域,有利有弊,利于方便自由,弊于作用域内的变量容易被共享,例如这个 ...

  5. ES6笔记(3)-- 解构赋值

    系列文章 -- ES6笔记系列 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组.对象.字符串的解构赋值等 一.数组的解构赋值 function ids() { ret ...

  6. ES6笔记(4)-- Symbol类型

    系列文章 -- ES6笔记系列 Symbol是什么?中文意思是标志.记号,顾名思义,它可以用了做记号. 是的,它是一种标记的方法,被ES6引入作为一种新的数据类型,表示独一无二的值. 由此,JS的数据 ...

  7. ES6笔记(6)-- Set、Map结构和Iterator迭代器

    系列文章 -- ES6笔记系列 搞ES6的人也是够无聊,把JS弄得越来越像Java.C++,连Iterator迭代器.Set集合.Map结构都出来了,不知道说什么好... 一.简单使用 1. iter ...

  8. ES6笔记(7)-- Promise异步编程

    系列文章 -- ES6笔记系列 很久很久以前,在做Node.js聊天室,使用MongoDB数据服务的时候就遇到了多重回调嵌套导致代码混乱的问题. JS异步编程有利有弊,Promise的出现,改善了这一 ...

  9. ES6 笔记汇总

    ES6 笔记汇总 二.ES6基础-let和const命令 三.变量的解构赋值 四.字符串的拓展 五.正则表达式的拓展 ...将会持续更新,敬请期待

  10. ES6笔记2

    ES6笔记2 Promise Promise 是 ES6 引入的异步编程的新解决方案,语法上是一个构造函数 一共有3种状态,pending(进行中).fulfilled(已成功)和rejected(已 ...

随机推荐

  1. GPRS优点介绍及GPRS上网相关知识(转)

    源:http://blog.chinaunix.net/uid-20745340-id-1878732.html 单片机微控制器以其体积小.功耗低.使用方便等特点,广泛应用于各种工业.民用的嵌入式系统 ...

  2. hibernate的优化

    1.使用双向一对多关联,不实用单项一对多2.不用一对一,使用一对多3.配置对象缓存,不使用集合缓存

  3. hibernate---一对一单向主键关联(不重要)

    比如, husband的id参考wife的id husband.java: package com.bjsxt.hibernate; import javax.persistence.Entity; ...

  4. C# DateTime变量不能赋null值

    使用定时器的时候: DateTime aimtime=DateTime.Now.AddSeconds(1); CheckTimer() { if(DateTime.Now.CompareTo(aimt ...

  5. (中等) POJ 1191 棋盘分割,DP。

    Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次 ...

  6. 关于LCD以及BMP和RGB565

    源: 关于LCD以及BMP和RGB565

  7. form表单传递下拉框的Value和Text值,不适用Jquery传递

    同时获取下拉框的Value和Text值的解决办法:添加一个<input type="text" >文本框,用户选中一项后就将该项的value值给他 然后接受页面获取该文 ...

  8. (简单) HDU 3397 Sequence operation,线段树+区间合并。

    Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...

  9. LPC1788的LCD接口驱动真彩屏

    #ifndef __LCD_H_ #define __LCD_H_ #include "common.h" #include "debugserial.h" # ...

  10. Web开发中需要了解的东西

    在StackExchange上有人问了这样一个问题:What should every programmer know about web development?(关于Web开发,什么是所有程序员需 ...