Generator函数

2019-06-27  本文已影响0人  gitblong
//Generator的简单语法
console.log("=========Generator的简单语法============")
//yield定义的表达式,只有next()函数才能执行直接调用 function* 的函数无法执行
function* helloWorldGenerator() {// 使用   function* 关键字定义Generator函数
    yield 'hello';               // 使用yield关键字 定义不同的内部状态
    yield 'world';
    return 'end';                // 停止该状态
}

var hw = helloWorldGenerator();
console.log(hw.next());

console.log(hw.next());
console.log(hw.next());
console.log(hw.next());
/*
{ value: 'hello', done: false }
{ value: 'world', done: false }
{ value: 'end', done: true }
{ value: undefined, done: true }
*/

//Generator的应用==》遍历一维+二维数组
console.log("=========Generator的应用==》遍历一维+二维数组============")
let arrYield = [1, [[2, 3], 4], [5, 6]];
let flat = function* (arr) {
    let length = arr.length;
    for (let i = 0; i < length; i++) {
        let item = arr[i];
        if (typeof item !== 'number') {
            yield* flat(item);
        } else {
            yield item;
        }
    }
}

for (let f of flat(arrYield)) {
    console.log(f);//1,2,3,4,5,6
}

//简单的Iterator函数生成方式
console.log("=========简单的Iterator函数生成方式============")
let myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
}

console.log([...myIterable]);//[1,2,3,4]

//Generator函数与Iterator接口的关系
console.log("=========Generator函数与Iterator接口的关系============")
function* gen() {}

let g = gen();
console.log(g[Symbol.iterator]() == g); //true

//next(true)返回上一个yield表达式的返回值
console.log("=========next(true)返回上一个yield表达式的返回值============")
function* previousYieldValue() {
    for (let i = 0; true; i++) {
        let reset = yield i;//reset 为next()函数传入的值
        console.log("reset",reset);
        if(reset) {i = i-2};
    }
}

let previousValue = previousYieldValue();
 console.log(previousValue.next());
 console.log(previousValue.next());
 console.log(previousValue.next());
 console.log(previousValue.next(true));
 console.log(previousValue.next());
/*
    { value: 0, done: false }
    reset undefined
    { value: 1, done: false }
    reset undefined
    { value: 2, done: false }
    reset true
    { value: 1, done: false }
    reset undefined
    { value: 2, done: false }
*/

//  next()函数是用于向generator函数进行状态变化时的过程中
//  next()方法的参数表示上一个yield表达式的返回值,所以第一次使用next方法时,传递参数是无效的
//  yeild定义的表达式将在next()函数调用时,将结果返回给next()函数,但不会再generator中执行
console.log("=========next()函数是用于向generator函数进行状态变化时的过程中    改变yield表达式内部值得一种方式============");
function* nextFoo(x) {
    let y = 2 * (yield(x + 1));
    let z = yield (y / 3);
    return (x + y + z);
}

let nextFA = nextFoo(5);
console.log(nextFA.next());
console.log(nextFA.next());
console.log(nextFA.next());
/*
{ value: 6, done: false }
{ value: NaN, done: false }
{ value: NaN, done: true }
*/
let nextFB = nextFoo(5);
console.log(nextFB.next());
console.log(nextFB.next(12));//设置上一个yield(x+1)的值为12 所以y为24  ->当前返回z = 8
console.log(nextFB.next(13));//设置上一个yield的值为13即z=13     x+y+z = 5+24+13 = 42
/*
{ value: 6, done: false }
{ value: 8, done: false }
{ value: 42, done: true }
*/

//使用next方法向函数内部输入值得例子
function* dataConsumer() {
    console.log('Started');
    console.log(`1.${yield 222}`);
    console.log(`2.${yield}`);
}

let consumer = dataConsumer();
console.log(consumer.next());
console.log(consumer.next('a'));
console.log(consumer.next('b'));
/*
Started
{ value: 222, done: false }
1.a
{ value: undefined, done: false }
2.b
{ value: undefined, done: true }
*/
//要想第一个next()就可以传值的写法
function wrapper(generatorFunction) {
    return function (...args) {
        let generatorObject = generatorFunction(...args);
        generatorObject.next();
        return generatorObject;
    };
}
const wrapped = wrapper(function* () {
    console.log(`First input: ${yield}`);
    return 'DONE';
})

console.log(wrapped().next('hello~'));
/*
First input: hello~
{ value: 'DONE', done: true }

*/

console.log("===========for...of循环自动遍历Generator函数,不需要使用next方法=============")
//for...of循环自动遍历Generator函数,不需要使用next方法
function* forOf() {
    yield 1;
    yield 2;
    return 3;
}

for (let v of forOf()) {
    console.log(v);//1,2
}

/*
    只显示了2个yield表达式的值,一旦next方法返回对象done属性为true,for...of循环就会终止,且不会返回该对象,所以return不包括在for...of循环中
*/

//使Object能使用for...of进行遍历
console.log('=====================使Object能使用for...of进行遍历========================');
function* objectEntries(obj) {
    let propKeys = Reflect.ownKeys(obj);

    for (let propKey of propKeys) {
        yield [propKey, obj[propKey]];
    }

}
let jane = {first:'Jane', last: 'Doe'}

for (let [key, value] of objectEntries(jane)) {
    console.log(`${key}:${value}`);/*first:Jane last:Doe*/
}

//Generator.prototype.throw()方法
console.log("==========Generator.prototype.throw()方法==================")
let throwFunction = function* () {
    try {
        yield 1;
    }catch (e) {
        console.log('内部捕获',e)
    }
    yield 2;
};

let i = throwFunction();
i.next();

try {
    console.log(i.throw('a'));//执行generator的catch方法后    自动执行下一个yield
    i.throw('b');//因为generator的catch方法已经执行过了,所以抛出异常
} catch (e) {
    console.log("外部捕捉",e);
}

/*
    内部捕获 a
    外部捕捉 b
*/

let i2 = throwFunction();
try {
    console.log(i2.throw('c'));//执行generator的catch方法后    自动执行下一个yield
}catch (e) {
    console.log("外部捕获", e);//外部捕获 c,因为未执行next方法,仍未到Generator函数内部
}
let i3 = throwFunction();
console.log(i3.next());
console.log(i3.next());

try{
    console.log(i3.throw('D'))//执行generator的catch方法后    自动执行下一个yield
}catch (e) {
    console.log('外部捕获', e);//外部捕获 D     因为第2个next外部没有try...catch语句
}
/*

内部捕获 a
{ value: 2, done: false }
外部捕捉 b
外部捕获 c
{ value: 1, done: false }
{ value: 2, done: false }
外部捕获 D

*/

//Generator.prototype.return()  终结遍历Generator函数
function* returnFunction() {
    yield 1;
    yield 2;
    yield 3;
}

let returnFun = returnFunction();
console.log(returnFun.next());
console.log(returnFun.return('foo'));
console.log(g.next());


//如果Generator函数内部哟try...finally代码块,且正在执行try代码块,那么return方法会推迟到finally代码块执行完在执行
function* numbers() {
    yield 1;
    try {
        yield 2;
        yield 3;
    }finally {
        yield 4;
        yield 5;
    }
    yield 6;
}

let numb = numbers();
console.log(numb.next());
console.log(numb.next());
console.log(numb.return(7));
console.log(numb.next());
console.log(numb.next());

/*
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: 7, done: true }
*/

//yield* 表达式    如果在Generator函数内部,调用另一个Generator函数,需要在前者的函数体内部,自己手动完成遍历
console.log("================yield* 表达式===================")
function* iteratorFunction() {
    yield 'a';
    yield 'b';
}

function* barFunction() {
    yield 'x';
    for (let i of iteratorFunction()) {
        console.log(i);//a,b
    }
    yield 'y';
}

for (let v of barFunction()) {
    console.log(v);//x,a,b,y
}

let stringsBarFunction = barFunction();
console.log(stringsBarFunction.next());
console.log(stringsBarFunction.next());
console.log(stringsBarFunction.next());
console.log(stringsBarFunction.next());
/*
{ value: 'x', done: false }
a
b
{ value: 'y', done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
*/

//使用    yield*  只要有Iterator接口就能实现遍历
function* yieldFunction() {
    yield 'x';
    yield* iteratorFunction();
    yield 'y';
}
//等同于
function* yieldBarFunction() {
    yield 'x';
    yield 'a';
    yield 'b';
    yield 'y';
}
//等同于
function* yieldBarForFunction() {
    yield 'x';
    for (let v of yieldFunction()) {
        yield v;
    }
    yield 'y';
}
for (let v of yieldFunction()) {
    console.log('yieldFunction', v);//x,a,b,y
}
let yieldFunction1 = yieldFunction();
console.log(yieldFunction1.next());
console.log(yieldFunction1.next());
console.log(yieldFunction1.next());
console.log(yieldFunction1.next());
/*
{ value: 'x', done: false }
{ value: 'a', done: false }
{ value: 'b', done: false }
{ value: 'y', done: false }
*/

//另一个例子
function* inner() {
    yield 'hello!';
    yield 'hello1!';

}

function* outer1() {
    yield 'open';
    yield inner();
    yield 'close';
}

let genOuter = outer1();
console.log(genOuter.next().value);//open
console.log(genOuter.next().value);//Object [Generator] {}
console.log(genOuter.next().value);//close
function* outer2() {
    yield 'open';
    yield* inner();
    yield 'close';
}

let genOuter2 = outer2();
console.log(genOuter2.next().value);//open
console.log(genOuter2.next().value);//hello!
console.log(genOuter2.next().value);//hello1!
console.log(genOuter2.next().value);//close


//如果被代理的Generator函数有return语句,那么久可以向代理它的Generator函数返回数据
function* fooReturn() {
    yield 2;
    yield 3;
    return 'fooReturn';
}

function* barFunctionReturn() {
    yield 1;
    let v = yield* fooReturn();
    console.log('v: ' + v);
    yield 4;
}

let it = barFunctionReturn();
console.log(it.next());//{ value: 1, done: false }
console.log(it.next());//{ value: 2, done: false }
console.log(it.next());//{ value: 3, done: false }
                       //v: fooReturn
console.log(it.next());//{ value: 4, done: false }
console.log(it.next());//{ value: undefined, done: true }

//作为对象属性的Generator函数简写成以下形式
let objGenerator = {
    * myGeneratorMetod() {

    },
    myGeneratorMetod2:function* () {

    }
}

//9.generator函数的this
//10.generator函数的含义
//11.Generator与上下文
//12应用
上一篇下一篇

猜你喜欢

热点阅读