日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第十五节:有一种特殊的函数叫:Generator函数

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第十五节:有一种特殊的函数叫: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函数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。