ES6 -- 從callback到Generator、Promise, 再到ES7的Async -- Part 2/5

這篇介紹Generator。

生成器(Generator)的概念: 當函式執行到yield會暫停(暫時離開function), 並將值回傳。直到再次呼叫Generator中的next()方法, 才會回到函式中繼續執行程式。

p.s. yield !== return。return是離開function, 且不會再回來。

簡言之, Generator就是個"迭代器", 直接實作了迭代器模式。



在ES5中, 當我們要將值迭代進一個陣列或物件時:

e.g.

function range1(start, end, step) {

    var list = [];
    while (start < end) {

        list.push(start);
        start += step;

    }

    return list;

}

var r = range1(0, 10, 2);

for (var i = 0; i < r.length; i++) {

    console.log(r[i]);                                                    // 0, 2, 4, 6, 8

}



在ES6中, 可使用Generator:

e.g.

function* range2(start, end, step) {                    // 有加 * 的函式, 代表裡面能使用yield

    while (start < end) {

        yield start
        start += step

    }

}

for (let i of range2(0, 10, 2)) {

    console.log(i)                                                        // 0, 2, 4, 6, 8

}



p.s. 這篇是Generator我覺得介紹的滿好的一篇:

初探 ES6(3)Generator
http://www.codedata.com.tw/javascript/es6-3-generator/

整篇可以看看。

這裡擷取Generator運作原理(本身的流程控制如下):


先來看看基本的語法與觀念。ES6 的Generator函數,需要用* modifier標注:
function * gen() {

  console.log('start');
  yield "called";

}


然後呼叫這個函數時,他不會直接執行,而是返回一個Generator物件:
var g = gen();
//nothing happened


接著要執行Generator物件的next方法,函數才會開始執行,到yield時會暫停執行並返回,返回值是一個物件,他的value屬性是yield右側的expression的執行結果:
var a = g.next();
//顯示start

console.log(a.value);
//顯示called


要判斷Generator是否執行完畢,可以用返回物件的done屬性來判斷:
console.log(a.done);
//顯示false


上面的Generator function只會執行一次yield,所以再次執行next()時,所取得物件的done屬性會變成true:
var b = g.next();
console.log(b.done);
//顯示true


由於Generator物件的迭代已經結束了,如果再呼叫他的next(),就會拋出例外:
g.next();
//在node.js環境中會拋出 Error: Generator has already finished



留言

熱門文章