Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 Generator 基礎 #1

Open
aszx87410 opened this issue Dec 3, 2018 · 0 comments
Open

ES6 Generator 基礎 #1

aszx87410 opened this issue Dec 3, 2018 · 0 comments
Labels
JS JavaScript

Comments

@aszx87410
Copy link
Owner

最近趁著有些時間研究了一下ES6,有個很重要的東西叫做Generator,但是這概念對我來說超級陌生
所以我覺得沒有很好上手,研究過一些資料以後終於搞懂是在做什麼
寫篇文章跟大家分享

首先,Generator 這東西之所以會不好上手,是因為
一個指令做兩件事情
只要記住這個原則,Generator就沒有那麼困難了

function *get_counter(){
  let i = 1;
  while(true){
    yield i;
    i++;
  }
}

var counter = get_counter();
console.log(counter.next().value);//1
console.log(counter.next().value);//2
console.log(counter.next().value);//3
console.log(counter.next().value);//4

一個簡單的計數器,在這邊可以很簡單的先想說,yield這個指令就是把東西丟出去
這邊應該滿好理解,但是generator難懂的地方就在於,除了把東西丟出去,還可以丟東西進來

function *get_adder(){
  let total = 0;
  while(true){
    console.log("before yield");
    total+=yield total;
    console.log("after yield, total:"+total);
  }
}

var adder = get_adder();
console.log(adder.next().value);
/*
before yield
0
*/
console.log(adder.next(100).value);
/*
after yield, total:100
before yield
100
*/

在執行第一次next()的時候,會先跑到console.log("before yield");,這很好懂
接著會先執行yield total,會先把total丟出去,所以會輸出0
接下來呢?還記得剛剛說過 yield除了丟值,還可以接受值,所以丟完以後,現在會等下一個值丟進來
於是程式就停住了,執行完第一次之後,會停留在輸出0的地方

接著執行第二次next(),我們把100傳進去,於是上一次的yield在等待的值就傳入了,會執行
total+=100;,然後輸出after yield, total:100
每呼叫一次next,都會跑到yield輸出值的地方!所以接著會跑到before yield然後把total,也就是100丟出去
接著等待下一個值

用比較好懂的方式,就是把yield拆成兩個指令

function *get_adder(){
  let total = 0;
  while(true){
    console.log("before yield");
    output(total);
    total+=input();
    console.log("after yield, total:"+total);
  }
}

每次next()的時候都會執行到output的地方
input則是會等待外面傳值進來

再來看一個範例

function *gen(){
  let arr = [];
  while(true){
    arr.push(yield arr);
  }
}

var name = gen();
console.log(name.next('init').value);//[]
console.log(name.next('nick').value);//["nick"]
console.log(name.next('peter').value);//["nick","peter"]

可以注意到的是,第一次的next()無論有沒有傳值其實都一樣
為什麼呢?還記得剛才提過,generator最重要的概念是:每次next()都會執行到yield丟值出去的地方
然後yield這個指令分成兩個步驟,先丟東西出去,再等東西進來
所以第一次的next(),跑到yield的第一個步驟就結束了,等第二次的next()傳東西進來

差不多就這樣了
重要的兩個概念就是:

  1. yield其實是兩個動作的合體:丟東西出去->等東西進來
  2. 每次next()都會跑到yield丟東西出來的那個步驟

ref:
拥抱Generator,告别异步回调
ES6 Generators 基礎教學

@aszx87410 aszx87410 added the JS JavaScript label Dec 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JS JavaScript
Projects
None yet
Development

No branches or pull requests

1 participant