1. 程式人生 > >es6之Generator

es6之Generator

object 每一個 undefined style es6 cti 另一個 world done

1.Generator函數其實是一個封裝了多個內部狀態的狀態機,執行它會返回一個遍歷器對象,然後可以依次遍歷Generator中的每一個狀態,也就是分段執行,yield是暫停執行的標記,next恢復執行。

2.yield:

- 一個函數裏面,return只能執行一遍,yield可以執行多次;

- Generator函數可以不用yield,這時就是一個簡單的暫緩執行函數;

- yield只能用在Generator函數裏;

- yield如果用在一個表達式裏,必須放在圓括號裏

function* foo() {
    console.log(‘hello‘ + (yield));
    console.log(
‘hello‘ + (yield ‘world‘)); }

- yield用於函數參數或放在賦值表達式的右邊,可以不加括號

function* demo() {
    foo(yield ‘a‘, yield ‘b‘);
    let input = yield;
}

3.可以把Generator函數賦值給對象的Symbol.iterator屬性,從而使對象具有Iterator接口

var obj = {};
obj[Symbol.iterator] = function* (){
    yield 1;
    yield 2;
};

[...obj] // [1,2]

4.next方法的參數會被當做上一個yield的返回值,這樣就可以在函數運行期間向內部傳值。

5.for...of會自動遍歷Generator函數生成的Iterator對象,不需要調用next方法。

// 實現Fibonacci數列
function* fib() {
    let [prev, curr] = [0, 1];
    for (;;) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}

for (let n of fib()) {
    if (n > 1000) break;
    console.log(n);
}

6.遍歷器對象的throw方法。

7.遍歷器對象的return方法可以返回給定的值且終結遍歷。

8.yield* 表達式用來在一個Generator函數裏調用另一個Generator函數,而後面這個函數其實就是for...of的一種簡寫;

- yield* 後面如果跟著數組,則會遍歷該數組;

- yield* 後面如果跟著字符串,也會遍歷字符串;

- 如果後面的Generator函數有return語句,那麽就可以像這個函數返回數據

function *foo() {
    yield 2;
    return "foo";
}

function *bar() {
    yield 1;
    var v = yield *foo();
    console.log( "v: " + v );
    yield 3;
}

var it = bar();

it.next() // {value: 1, done: false}
it.next() // {value: 2, done: false}
it.next() // "v: foo"
          // {value: 3, done: false}
it.next() // {value: undefined, done: true}

9.作為屬性的Generator: let obj = { * foo(){}};

10.Generator函數返回的遍歷器對象是函數的實例,也繼承了函數的prototype上的方法;

// 使用this
function* F() {
    this.a = 1;
    yield this.b = 2;
}
var f = F.call(F.prototype);

f.next();  // Object {value: 2, done: false}
f.next();  // Object {value: undefined, done: true}

f.a // 1
f.b // 2

11.Generator函數的應用:

- 異步操作可以用同步寫法;

- 控制流管理;

- 部署Iterator接口;

12.協程:多個線程互相協作,完成異步任務;Generator函數就是協程在es6的實現,其特點是交出函數的執行權。

13.Thunk函數其實就是傳名調用,將參數放到一個臨時函數中,用來替換某個表達式傳入函數體。

function f(m) {
  return m * 2;
}

f(x + 5);

// 等同於

var thunk = function () {
  return x + 5;
};

function f(thunk) {
  return thunk() * 2;
}

在js中,js是傳值調用,Thunk 函數替換的不是表達式,而是多參數函數,將其替換成一個只接受回調函數作為參數的單參數函數。Thunk 函數是自動執行 Generator 函數的一種方法。

// 正常版本的readFile(多參數版本)
fs.readFile(file, callback);

// Thunk版本的readFile(單參數版本)
var Thunk = function (file) {
  return function (callback) {
    return fs.readFile(file, callback);
  };
};

var readFileThunk = Thunk(file);
readFileThunk(callback);

es6之Generator