美文网首页
Generator函数

Generator函数

作者: gitblong | 来源:发表于2019-06-27 22:43 被阅读0次
    //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应用
    

    相关文章

      网友评论

          本文标题:Generator函数

          本文链接:https://www.haomeiwen.com/subject/baodcctx.html