Generator函數(shù)

//Generator的簡單語法
console.log("=========Generator的簡單語法============")
//yield定義的表達式,只有next()函數(shù)才能執(zhí)行直接調(diào)用 function* 的函數(shù)無法執(zhí)行
function* helloWorldGenerator() {// 使用   function* 關鍵字定義Generator函數(shù)
    yield 'hello';               // 使用yield關鍵字 定義不同的內(nèi)部狀態(tài)
    yield 'world';
    return 'end';                // 停止該狀態(tài)
}

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的應用==》遍歷一維+二維數(shù)組
console.log("=========Generator的應用==》遍歷一維+二維數(shù)組============")
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函數(shù)生成方式
console.log("=========簡單的Iterator函數(shù)生成方式============")
let myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
}

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

//Generator函數(shù)與Iterator接口的關系
console.log("=========Generator函數(shù)與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()函數(shù)傳入的值
        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()函數(shù)是用于向generator函數(shù)進行狀態(tài)變化時的過程中
//  next()方法的參數(shù)表示上一個yield表達式的返回值,所以第一次使用next方法時,傳遞參數(shù)是無效的
//  yeild定義的表達式將在next()函數(shù)調(diào)用時,將結(jié)果返回給next()函數(shù),但不會再generator中執(zhí)行
console.log("=========next()函數(shù)是用于向generator函數(shù)進行狀態(tài)變化時的過程中    改變yield表達式內(nèi)部值得一種方式============");
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方法向函數(shù)內(nèi)部輸入值得例子
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循環(huán)自動遍歷Generator函數(shù),不需要使用next方法=============")
//for...of循環(huán)自動遍歷Generator函數(shù),不需要使用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循環(huán)就會終止,且不會返回該對象,所以return不包括在for...of循環(huán)中
*/

//使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('內(nèi)部捕獲',e)
    }
    yield 2;
};

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

try {
    console.log(i.throw('a'));//執(zhí)行generator的catch方法后    自動執(zhí)行下一個yield
    i.throw('b');//因為generator的catch方法已經(jīng)執(zhí)行過了,所以拋出異常
} catch (e) {
    console.log("外部捕捉",e);
}

/*
    內(nèi)部捕獲 a
    外部捕捉 b
*/

let i2 = throwFunction();
try {
    console.log(i2.throw('c'));//執(zhí)行generator的catch方法后    自動執(zhí)行下一個yield
}catch (e) {
    console.log("外部捕獲", e);//外部捕獲 c,因為未執(zhí)行next方法,仍未到Generator函數(shù)內(nèi)部
}
let i3 = throwFunction();
console.log(i3.next());
console.log(i3.next());

try{
    console.log(i3.throw('D'))//執(zhí)行generator的catch方法后    自動執(zhí)行下一個yield
}catch (e) {
    console.log('外部捕獲', e);//外部捕獲 D     因為第2個next外部沒有try...catch語句
}
/*

內(nèi)部捕獲 a
{ value: 2, done: false }
外部捕捉 b
外部捕獲 c
{ value: 1, done: false }
{ value: 2, done: false }
外部捕獲 D

*/

//Generator.prototype.return()  終結(jié)遍歷Generator函數(shù)
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函數(shù)內(nèi)部喲try...finally代碼塊,且正在執(zhí)行try代碼塊,那么return方法會推遲到finally代碼塊執(zhí)行完在執(zhí)行
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函數(shù)內(nèi)部,調(diào)用另一個Generator函數(shù),需要在前者的函數(shù)體內(nèi)部,自己手動完成遍歷
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接口就能實現(xiàn)遍歷
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函數(shù)有return語句,那么久可以向代理它的Generator函數(shù)返回數(shù)據(jù)
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函數(shù)簡寫成以下形式
let objGenerator = {
    * myGeneratorMetod() {

    },
    myGeneratorMetod2:function* () {

    }
}

//9.generator函數(shù)的this
//10.generator函數(shù)的含義
//11.Generator與上下文
//12應用
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容