第十五节:有一种特殊的函数叫:Generator函数
????????今天我們來學習ES6給我們帶來的一種新函數,在學習它之前,前端君希望你已經閱讀并初步了解了上一節的內容:iterator遍歷器。因為本節的內容,是建立在iterator遍歷器知識的基礎上。
????????如果是新來的童鞋,或者您還未了解iterator遍歷器,我希望你可以先學習上一節的內容,點擊可查看:第十四節iterator遍歷器的介紹。
?
????????既然你都看到這里來了,就咱們就接著往下講...
聲明Generator函數
????????
????????我們要學習的這個新函數叫做:Generator函數,又稱生成器函數,是ES6的一個重要的新特性。
?
????????我們來看看這個函數張什么模樣:
? ?//聲明一個Hello的Generator函數
? ?function* Hello(name) {
? ???? yield `hello ${name}`;
? ???? yield `how are you`;
? ???? yield `bye`;
? ?}
? ?
????????上面這個就是Generator函數,乍一看,是不是跟普通的函數沒什么兩樣?確實很像,但是我們要知道它有兩個重要的區別:
普通函數用function來聲明,Generator函數用function*聲明。
Generator函數內部有新的關鍵字:yield,普通函數沒有。
????????PS:函數體內用到了ES6的新特性:字符串模板。第六節的內容,點擊可以查看。
?
????????了解了Generator函數的聲明方式,我們又多了兩個疑問:
Generator函數運行起來會發生什么?
關鍵字yield語句的作用是什么?
調用Generator函數
????????
????????帶著這兩個疑問我們往下看,我們試著就調用一下這個名字叫Hello的Generator函數,看看會發生什么:
? ?//聲明一個Hello的Generator函數
? ?function* Hello(name) {
? ???? yield `hello ${name}`;
? ? ??? yield `how are you`;
?? ? ?? yield `bye`;
? ?}
? ?//調用Hello函數
? ?let ite = Hello('前端君');
? ?//結果:[object Generator]
? ?ite.next();
? ?//{value: "hello 前端君", done: false}
? ?ite.next();
? ?//{value: "how are you", done: false}
? ?ite.next();
? ?//{value: "bye", done: false}
? ?ite.next();
? ?//{value: undefined, done: true}
????????看到這里,估計你也看到了一個熟悉的面孔:next()方法。(上一節iterator遍歷器的內容)。
????????我們一起看看整個過程發生了什么:
????????一開始,我們調用Hello(“前端君”),函數執行后,返回了一個:[object Genrator]生成器對象,我們把它賦值到變量ite中,僅此而已,并沒有做太多的事情。
????????接著,第1次調用生成器對象ite的next( )方法,返回了一個對象:
? ?{value: "hello 前端君", done: false}
????????第2次調用生成器對象ite的next( )方法,同樣得到了一個對象:
? ?{value: "how are you", done: false}
????????第3次調用生成器對象ite的next( )方法,又得到了一個對象:
? ?{value: "bye", done: false}
????????直到,第4次調用生成器對象ite的next( )方法,返回的對象:
? ?{value: undefined, done: true}
????????看到這里有沒有發現,這里生成器的next( )方法的和遍歷器iterator的next( )方法的返回結果是不是一樣?
????????沒錯,你可以把Generator函數被調用后得到的生成器理解成一個遍歷器iterator,用于遍歷函數內部的狀態。(所以要求大家先學習第十三節iterator遍歷器的知識)
Generator函數的行為
????????
????????通過上面的案例,我們知道了:Generator函數被調用后并不會一直執行到最后,它是先回返回一個生成器對象,然后hold住不動,等到生成器對象的next( )方法被調用后,函數才會繼續執行,直到遇到關鍵字yield后,又會停止執行,并返回一個Object對象,然后繼續等待,直到next( )再一次被調用的時候,才會繼續接著往下執行,直到done的值為true。
?
yield語句的作用
????????而yield在這里起到了十分重要的作用,就相當于暫停執行并且返回信息。有點像傳統函數的return的作用,但不同的是普通函數只能return一次,但是Generator函數可以有很多個yield。而return代表的是終止執行,yield代表的是暫停執行,后續通過調用生成器的next( )方法,可以恢復執行。
?
next( )方法接收參數
????????
????????此外,next( )方法還可以接受一個參數,它的參數會作為上一個yield的返回值,我們來看一下:
? ?//聲明一個Hello的Generator函數
? ?function* Hello() {
? ? ??? let res = yield `hello`;
? ???? yield res;
? ?}
? ?
? ?let iterator = Hello();
? ?//結果:一個生成器對象
? ?iterator.next();
? ?//結果:{value: "hello", done: false}
? ?iterator.next("前端君");
? ?//結果:{value: "前端君", done: false}
????????注意函數體內的第一個yield關鍵字,我們把它的返回值賦值給了一個變量res。
?
????????再看2次next方法的調用:
????????第1次調用next( )方法,返回的對象屬性value值為“hello”,屬性done值為:fasle,并暫停執行。
????????第2次next( )方法,傳入參數:字符串“前端君”。此時,第二個yield關鍵字緊跟著的是變量res,而變量res的值正是上一個關鍵字yield的返回值。也就是說這個值正是我們傳入的參數:“前端君”。因為:next( )的參數會作為上一個yield的返回值。
????????慢慢體會一下,理清邏輯,稍微有點繞。?
關鍵字yield*
????????
????????在一個Generator函數里面,如果我們想調用另一個Generator函數,就需要用到的關鍵字是:yield*。
????????我們來看看怎么玩,代碼有點長,但是很好理解:
? ?//聲明Generator函數:gen1? ?
? ?function* gen1() {
?? ? ?? yield "gen1 start";
? ? ??? yield "gen1 end";
? ?}
? ?//聲明Generator函數:gen2
? ?function* gen2() {
? ? ??? yield "gen2 start";
? ? ??? yield "gen2 end";
? ?}
? ?//聲明Generator函數:start
? ?function* start() {
?? ? ?? yield "start";
?? ? ?? yield* gen1();
?? ? ?? yield* gen2();
?? ? ?? yield "end";
? ?}
? ?//調用start函數
? ?var ite = start();
? ?//創建一個生成器
? ?
? ?ite.next();
? ?//{value: "start", done: false}
? ?ite.next();
? ?//{value: "gen1 start", done: false}
? ?ite.next();
? ?//{value: "gen1 end", done: false}
? ?ite.next();
? ?//{value: "gen2 start", done: false}
? ?ite.next();
? ?//{value: "gen2 end", done: false}
? ?ite.next();
? ?//{value: "end", done: false}
? ?
????????我們主要看start( )這個Generator函數,其中有兩句代碼:
? ?yield* gen1();
? ?yield* gen2();
????????這里使用了關鍵字yield*來實現調用另外兩個Generator函數。從后面的多個next( )方法得到的結果看,我們可以知道:
????????如果一個Generator函數A執行過程中,進入(調用)了另一個Generator函數B,那么會一直等到Generator函數B全部執行完畢后,才會返回Generator函數A繼續執行。
Generator函數的用途
????????
????????以上就是對Generator函數的講解介紹,它是ES6的一個很重要的新特性。它可以控制函數的內部狀態,依次遍歷每個狀態;可以根據需要,輕松地讓函數暫停執行或者繼續執行。
????????根據這個特點,我們可以利用Generator函數來實現異步操作的效果。
????????原理是:利用Generator函數暫停執行的作用,可以將異步操作的語句寫到yield后面,通過執行next方法進行回調。
?
本節小結?
總結:Generator函數是一種特殊的函數,可以使用關鍵字yield和next( )實現暫停和繼續執行,而關鍵字yield*專門用于調用Generator函數,看似簡單的特性,在實際開發中卻有極大的用處。
總結
以上是生活随笔為你收集整理的第十五节:有一种特殊的函数叫:Generator函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【云炬大学生创业基础笔记】第1章第3节
- 下一篇: 【云炬大学生创业基础笔记】第1章第3节