generator

  • 运行generator代码需要Node.js version > 0.11.3,在运行时,使用 node --harmony xx.js  方式运行。*

在 ES6 规范中,定义一个生成器函数,在 function 后跟上*即可定义:

function* gf() { };
function *gf() { };
function * gf() { };

以上三种方式都是对的。

gf.constructor; // function GeneratorFunction() { [native code] }

调用生成器函数会产生一个生成器(generator)对象。生成器拥有的最重要的方法是 next(),用来迭代:

function* gf(){
    console.log("hello");
}

gf();

运行后,终端并没打印出 hello,这是因为:调用生成器函数会产生一个生成器(generator)对象,但不会执行里面的代码,需要调用next()函数。

function* gf(){
    console.log("hello");
}

var g = gf();
g.next();

g是一个generator对象,调用next方法后,将真正[进入]gf函数体。

sex通常generator用理论讲解的很多,我们采用实例规律法进行学习,也就是通过多个例子来学会一种知识的使用,找到其规律;这个好处是,快速掌握并实际应用,避免学习大量理论后反而出不来。fuck

sex根据上面的例子,会发现generator有个断点效果,就是在执行方法体之前,等待调用next方法。

通常generator函数和yield关键词一起使用。yield可以理解为添加1个断点,看下面的例子:

function* gf(){

    console.log("start");

    var str = yield "hello"

    console.log("result",str);
}

var g = gf();
g.next();

fuck调用一次next,进入了函数,打印出 start , 这时遇到yield 所以终端了,我们后面继续调用一个 next 方法:good

function* gf(){

    console.log("start");

    var str = yield "hello"

    console.log("result",str);
}

var g = gf();
g.next();
g.next();

打印出:

start
result undefined

好像和我们预期的不一样,第一感觉应该是 result hello ,而不是 result undefined ,这是因为yield 后面跟着的语句确实返回了,只不过返回的hello值不是给了 str 变量,而是在第一次调用 g.next() 时,它会返回一个对象,这个对象里有个 value 属性,这个属性值就是 hello 。我们修改一下代码:

function* gf(){

    console.log("start");

    var str = yield "hello"

    console.log("result",str);
}

var g = gf();
var value = g.next().value;
console.log("yield value -> ",value);
//g.next();

结果:

start
yield value ->  hello

也就是第一次调用 next后,进入函数题,遇到yield确实中断了,准确解释是:中断并把 yield 的右侧的值,写入本次调用next生成的对象中,这个对象的value就是右侧的值。

而第二次调用next方法后,yield会把next(args)方法的 args值赋予左侧变量,并继续执行语句,下面的代码是我们想要的结果:

function* gf(){

    console.log("start");

    var str = yield "hello"

    console.log("result",str);
}

var g = gf();
var value = g.next().value;
g.next(value);

结果:god

start
result hello

next方法返回的对象有两个值,{value , done} value 表示yield右侧的值(也可能是generator函数的return值);done如果是false,表示后面还有未执行的yield语句。

sex下面做几个练习,根据不同的调用,分析终端输出结果:

function *test() {
    console.log("start");

    var a = yield "a";
    console.log(a, " - inside");

    var b = yield "b";
    console.log(b, " - inside");

    var c = yield "c";
    console.log(c, " - inside");

    return "game over";
}

这是个generator函数,下面是执行语句,你需要思考终端打印结果,有不理解的可在线提问:book

1.

test();

2.

var g = test();
g.next();

3.

var g = test();
var a = g.next();
console.log(a.value);

4.

var g = test();
var a = g.next();
console.log(a.value);
var b = g.next(a.value);

5.god

var g = test();
var a = g.next();
console.log(a.value);
var b = g.next(a.value);
console.log(b.value);
var c = g.next(b.value);
console.log(c.value);
var d = g.next(c.value);
console.log(d.value);

对ES6 generator 生成器就介绍到这里,下一节我们学习使用co 库,它是建立在 generator基础之上的,主要用于优化异步回调方式,让异步函数的调用和同步一样简单,使用体验要比 promise/A+ 更好。