Javascript生成器(Generator)的介紹與使用
什么是生成器?
生成器是在函數(shù)內(nèi)部運(yùn)行的一些代碼
- 返回值后,它會(huì)自行暫停,并且——
- 調(diào)用程序可以要求取消暫停并返回另一個(gè)值
這種“返回”不是傳統(tǒng)的從函數(shù) return。所以它被賦予了一個(gè)特殊的名稱——yield。
生成器語(yǔ)法因語(yǔ)言而異。Javascript 的生成器語(yǔ)法類似于 PHP,但是區(qū)別也很大,如果你希望它們的作用相同,那么最終你會(huì)感到非常困惑。
在 javascript 中,如果想要使用生成器,則需要:
- 定義特殊的生成器函數(shù)
- 調(diào)用該函數(shù)創(chuàng)建一個(gè)生成器對(duì)象
- 在循環(huán)中使用該生成器對(duì)象,或直接調(diào)用其 next 方法
我們以下面這個(gè)簡(jiǎn)單的程序做為起點(diǎn),并執(zhí)行以下每個(gè)步驟:
// File: sample-program.js function *createGenerator() { for(let i=0;i<20;i++) { yield i } } const generator = createGenerator() console.log(generator.next()) console.log(generator.next())
如果運(yùn)行這段代碼,則會(huì)得到以下輸出:
$ node sample-program.js
{ value: 0, done: false }
{ value: 1, done: false }
下面我來(lái)解釋該程序是如何工作的。
生成器函數(shù)
首先,代碼中存在生成器函數(shù)的定義:
function* createGenerator() { for(let i=0;i<20;i++) { yield i } }
function 后面的 * 告訴 javascript 這是一個(gè)生成器函數(shù)。以下寫(xiě)法都是生成器函數(shù)的有效定義。
function*createGenerator function* createGenerator function *createGenerator
* 并不是函數(shù)名的一部分。而是 function* 符號(hào)定義了生成器。
調(diào)用生成器函數(shù)
定義了生成器函數(shù)后,我們將其命名為其他名稱的函數(shù)。
// 注意:當(dāng)調(diào)用時(shí),沒(méi)有 *。 * 不是函數(shù)名稱的一部分 // `function *` 是用于定義生成器函數(shù)的符號(hào) const generator = createGenerator()
但是要記住:createGenerator 函數(shù)沒(méi)有返回值。這是因?yàn)樯善骱瘮?shù)沒(méi)有傳統(tǒng)的返回值。相反,當(dāng)你直接調(diào)用生成器函數(shù)時(shí),它總是返回實(shí)例化的 Generator 對(duì)象。
這個(gè)生成器對(duì)象具有一個(gè) next 方法。調(diào)用 next 將在生成器函數(shù)內(nèi)部運(yùn)行代碼。
function* createGenerator() { for(let i=0;i<20;i++) { yield i } }
這很重要,足以再次調(diào)用它。直接調(diào)用生成器函數(shù)不會(huì)在生成器函數(shù)中運(yùn)行任何代碼。而是創(chuàng)建一個(gè)生成器對(duì)象。它在生成器對(duì)象上調(diào)用 next,從而調(diào)用生成器函數(shù)中的代碼。
首次在生成器對(duì)象上調(diào)用 next 時(shí),內(nèi)部代碼將會(huì)一直運(yùn)行,直到出現(xiàn) yield 語(yǔ)句。一旦執(zhí)行到 yield,javascript 將會(huì)暫停該代碼的執(zhí)行,而 next 將返回(即給你,或yield)一個(gè)對(duì)象,該對(duì)象包含 yield 行中的值。
當(dāng)你第二次(或第三次、第四次甚至更多次)再調(diào)用 next 時(shí),代碼將會(huì)取消暫停并繼續(xù)運(yùn)行(在上次調(diào)用時(shí)中斷的地方)。變量(例如本例中的 i )將會(huì)保持它的值。當(dāng)代碼到達(dá)另一個(gè) yield 語(yǔ)句時(shí),該函數(shù)會(huì)再次暫停,并返回一個(gè)包含 yield 值的對(duì)象。
這就是為什么我們要調(diào)用兩次 next
console.log(generator.next()) console.log(generator.next())
會(huì)得到以下輸出:
{ value: 0, done: false }
{ value: 1, done: false }
生成器函數(shù)中的代碼執(zhí)行完畢后,將來(lái)對(duì) next 的任何調(diào)用都會(huì)返回一個(gè)對(duì)象,該對(duì)象的值為 undefined 且done 設(shè)置為 true。
{ value: undefined, done: true }
生成器和循環(huán)
雖然可以在生成器對(duì)象上手動(dòng)調(diào)用 next,但我們主要是要在循環(huán)中使用??匆幌逻@個(gè)稍作修改的程序。
// File: sample-program.js @highlightsyntax@jscript function *createGenerator() { for(let i=0;i<5;i++) { yield i } } const generator = createGenerator() for(const value of generator) { console.log(value) }
當(dāng)在 for...of 循環(huán)中使用生成器對(duì)象時(shí),每次循環(huán)都會(huì)在生成器對(duì)象上調(diào)用 next,并用產(chǎn)生的值填充變量(上面的 value)。運(yùn)行該程序?qū)?huì)輸出以下內(nèi)容:
$ node sample-program.js
0
1
2
3
4
在下一篇文章中,我們將更深入地探討 for ... of 循環(huán),并探索怎樣為 javascript 提供一種內(nèi)置方法來(lái)循環(huán) javascript 中的任何對(duì)象。
總結(jié)
到此這篇關(guān)于Javascript生成器(Generator)的文章就介紹到這了,更多相關(guān)Javascript生成器(Generator)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript調(diào)用客戶端的可執(zhí)行文件(示例代碼)
這篇文章主要是對(duì)JavaScript調(diào)用客戶端的可執(zhí)行文件(示例代碼)進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11JS中判斷某個(gè)字符串是否包含另一個(gè)字符串的五種方法
本文給大家?guī)?lái)JS中判斷某個(gè)字符串是否包含另一個(gè)字符串的五種方法,有string對(duì)象的方法,match() 方法,RegExp對(duì)象的方法,test() 方法,exec() 方法,具體內(nèi)容詳情大家參考下本文2018-05-05詳解?Map?和?WeakMap?區(qū)別以及使用場(chǎng)景
這篇文章主要介紹了詳解?Map?和?WeakMap?區(qū)別以及使用場(chǎng)景,Map本質(zhì)上是一個(gè)鍵值對(duì)的集合,WeakMap?只能將對(duì)象作為鍵名,下面來(lái)一起倆姐更多詳細(xì)內(nèi)容吧,希望這一篇文章能讓你對(duì)?Map?有更好的理解,或者能夠幫你理解?Map?和?WeakMap2022-01-01小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)的示例代碼
這篇文章主要介紹了小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Java與JavaScript中判斷兩字符串是否相等的區(qū)別
這篇文章主要介紹了Java與JavaScript中判斷兩字符串是否相等的區(qū)別,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03基于rollup的組件庫(kù)打包體積優(yōu)化小結(jié)
這篇文章主要介紹了基于rollup的組件庫(kù)打包體積優(yōu)化小結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06Echarts橫向堆疊柱狀圖和markLine實(shí)例詳解
一些柱形圖在數(shù)據(jù)量比較多的時(shí)候,橫向排列受到擠壓,導(dǎo)致柱形圖,變的非常細(xì),影響整體的效果,所以應(yīng)該將柱形圖堆疊起來(lái),這樣就會(huì)好很多,下面這篇文章主要給大家介紹了關(guān)于Echarts橫向堆疊柱狀圖和markLine的相關(guān)資料,需要的朋友可以參考下2022-06-06