今天討論的新特性讓我很是興奮,由於這個特性是 ES6 中最神奇的特性。html
這裏的「神奇」意味着什麼呢?對於初學者來講,該特性與以往的 JS 徹底不一樣,甚至有些晦澀難懂。從某種意義上說,它徹底改變了這門語言的一般行爲,這不是「神奇」是什麼呢。git
不只如此,該特性還能夠簡化程序代碼,將複雜的「回調堆棧」改爲直線執行的形式。程序員
我是否是鋪墊的太多了?下面開始深刻介紹,你本身去判斷吧。github
什麼是 Generator?web
看下面代碼:多線程
1
2
3
4
5
6
7
8
|
function* quips(name) {
yield "hello " + name + "!";
yield "i hope you are enjoying the blog posts";
if (name.startsWith("X")) {
yield "it's cool how your name starts with X, " + name;
}
yield "see you later!";
}
|
上面代碼是模仿 Talking cat(當下一個很是流行的應用)的一部分,點擊這裏試玩,若是你對代碼感到困惑,那就回到這裏來看下面的解釋。函數
這看上去很像一個函數,這被稱爲 Generator 函數,它與咱們常見的函數有不少共同點,但還能夠看到下面兩個差別:post
function
開始,但 Generator 函數以 function*
開始。yield
是一個關鍵字,和 return
有點像。不一樣點在於,全部函數(包括 Generator 函數)都只能返回一次,而在 Generator 函數中能夠 yield 任意次。yield 表達式暫停了 Generator 函數的執行,而後能夠從暫停的地方恢復執行。常見的函數不能暫停執行,而 Generator 函數能夠,這就是這二者最大的區別。性能
調用 quips()
時發生了什麼?ui
1
2
3
4
5
6
7
8
9
10
|
> var iter = quips("jorendorff");
[object Generator]
> iter.next()
{ value: "hello jorendorff!", done: false }
> iter.next()
{ value: "i hope you are enjoying the blog posts", done: false }
> iter.next()
{ value: "see you later!", done: false }
> iter.next()
{ value: undefined, done: true }
|
咱們對普通函數的行爲很是熟悉,函數被調用時就當即執行,直到函數返回或拋出一個異常,這是全部 JS 程序員的次日性。
Generator 函數的調用方法與普通函數同樣:quips("jorendorff")
,但調用一個 Generator 函數時並無當即執行,而是返回了一個 Generator 對象(上面代碼中的 iter
),這時函數就當即暫停在函數代碼的第一行。
每次調用 Generator 對象的 .next()
方法時,函數就開始執行,直到遇到下一個 yield 表達式爲止。
這就是爲何咱們每次調用 iter.next()
時都會獲得一個不一樣的字符串,這些都是在函數內部經過 yield 表達式產生的值。
當執行最後一個 iter.next()
時,就到達了 Generator 函數的末尾,因此返回結果的 .done
屬性值爲 true
,而且 .value
屬性值爲 undefined
。
如今,回到 Talking cat 的 DEMO,嘗試在代碼中添加一些 yield 表達式,看看會發生什麼。
從技術層面上講,每當 Generator 函數執行遇到 yield 表達式時,函數的棧幀 — 本地變量,函數參數,臨時值和當前執行的位置,就從堆棧移除,可是 Generator 對象保留了對該棧幀的引用,因此下次調用 .next()
方法時,就能夠恢復並繼續執行。
值得提醒的是 Generator 並非多線程。在支持多線程的語言中,同一時間能夠執行多段代碼,並伴隨着執行資源的競爭,執行結果的不肯定性和較好的性能。而 Generator 函數並非這樣,當一個 Generator 函數執行時,它與其調用者都在同一線程中執行,每次執行順序都是肯定的,有序的,而且執行順序不會發生改變。與線程不一樣,Generator 函數能夠在內部的 yield 的標誌點暫停執行。
經過介紹 Generator 函數的暫停、執行和恢復執行,咱們知道了什麼是 Generator 函數,那麼如今拋出一個問題:Generator 函數到底有什麼用呢?
參考:http://web.jobbole.com/82903/