//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應用
Generator函數(shù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
相關閱讀更多精彩內(nèi)容
- 廖雪峰老師----JavaScript教程 一.sort() 排序的核心?比較兩個元素的大小 問題: 因為:Arr...
- Symbol Iterator遍歷器 Generator函數(shù) async函數(shù) class 通過class定義類/實...
- generator函數(shù) yield next() 可以控制代碼執(zhí)行的暫停與恢復,但不改變執(zhí)行順序 async aw...
- 讓我們來想想generator函數(shù)和async有啥區(qū)別?唯一的區(qū)別是async函數(shù)會自動執(zhí)行,而generator...
- 參考鏈接:http://www.ruanyifeng.com/blog/2015/04/generator.htm...