在寫其餘 js 代碼時會常常用到 debugger
的東西,可以讓當前運行的函數暫停住。生成器函數裏的 yield
關鍵詞也能使得函數暫停運行,同時還能用來作數據的輸入輸出(若是是 debugger
,只能手動去逐個 inspect 變量)。html
yield
能夠看成「斷點」。yield value
除了能看成斷點,還能夠向外部輸出 value。react
此外,yield
表達式自己也是能夠有值的,也就是說還能夠表示外部傳入的數據。只要外部在調用 next(inputValue)
時輸入一個值。 這就是爲何在賦值語句裏,能夠用 yield
做爲右值(例如,在使用了 react-saga 的項目裏處處都是這種玩意兒)。git
function* fn1(){
var data = yield "字符串反轉器已啓動"
yield data.split("").reverse().join("")
}
// 建立 Generator 對象
var g = fn1()
// 運行函數,直到遇到第一個「斷點」(yield 處)
console.log(g.next())
// 上次停頓的位置是 var data = yield "字符串反轉器已啓動"
// 所以能夠在繼續運行前,使得 (yield "字符串反轉器已啓動") 的值爲 "Hello"
console.log(g.next("Hello"))
// 輸出:
// { value: '字符串反轉器已啓動', done: false }
// { value: 'olleH', done: false }
複製代碼
正如前面的示例,調用一個 function*
生成器函數,會返回一個 Generator 對象(上文的 g
)。這個對象是可迭代對象(最多見的用法,即用於 for of
循環中)。github
此外,能夠把它看成一個控制器,控制着一個被 yield
打了斷點(並且還沒開始運行)的函數。數組
Generator 其具有下列方法:bash
next(inputValue?): { value, done }
yield
或者 return
inputValue
。能夠在繼續運行生成器函數前,爲上次停頓所在的 yield 表達式設置一個值。throw(e): { value, done }
yield
停頓的位置 throw 一個異常,而後繼續運行,直到遇到 yield
、 return
或者未被捕獲的異常(見下文)return(value): {value, done}
[Symbol.iterator]()
next()
和 yield
關鍵詞相比,多了一個星號。能夠把 yield* another_iterable
看成如下代碼語法糖:編輯器
for (let item of another_iterable) {
yield item;
}
複製代碼
也就是說,在生成器函數裏, yield*
就是針對一個可迭代對象,把它的每一項逐個地 yield
出來。函數
有趣的例子:ui
yield* [1,2,3]
會把3個數字逐個 yield 出來。數組是可迭代的。yield* "abcdefg"
會把這7個字母逐個 yield 出來。字符串也是可迭代對象。yield* another_generator
至關於把另外一個 Generator 的輸出,看成本身的輸出給一個個 yield 出去了。
another_generator.next().value
就好了由 next()
或者 throw(e)
可讓生成器函數開始運行。在運行過程當中,若是生成器函數裏遇到了未被捕獲的異常(能夠是生成器內部本身產生的,或者由外部調用 throw(e)
塞進去的),那麼會在外部由 next()
或者 throw(e)
給 throw 出來spa
function* test(){
try {
console.log("inner: Hello")
console.log("inner: GET" + (yield "output1"))
} catch (err) {
console.log("inner: Caught", err)
}
console.log("inner: Done")
return "output 2"
}
var g = test()
console.log("outer: next: ", g.next("input 1"))
console.log("outer: throw: ", g.throw("err"))
console.log("outer: next: ", g.next("input 2"))
複製代碼
上面的例子輸出以下。注意到由外部提供的 input1
不會被輸出,由於那是生成器函數還沒開始運行的時候傳進去的,能傳到哪裏?沒有任何的意義。
inner: Hello
outer: next: { value: 'output1', done: false }
inner: Caught err
inner: Done
outer: throw: { value: 'output 2', done: true }
outer: next: { value: undefined, done: true }
複製代碼
安利
寫了一個 Markdown 編輯器組件,只要一個框,所見即所得,並且還全面兼容 CodeMirror(一個很強大的代碼編輯組件)
悄悄安利一下: laobubu.net/HyperMD/