1.Generator函數其實是一個封裝了多個內部狀態的狀態機,執行它會返回一個遍歷器對象,然後可以依次遍歷Generator中的每一個狀態,也就是分段執行,yield是暫停執行的標記,next恢復執行。 2.yield: - 一個函數裡面,return只能執行一遍,yield可以執行多次; - G ...
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);