<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          遞歸執(zhí)行上下文和堆棧

          共 1973字,需瀏覽 4分鐘

           ·

          2021-02-04 21:58

          遞歸執(zhí)行上下文和堆棧

          我們接著昨天的遞歸繼續(xù)講述關(guān)于遞歸的執(zhí)行上下文,以及堆棧。

          現(xiàn)在,讓我們檢查一下遞歸調(diào)用是如何工作的。為此,我們將深入研究功能。

          有關(guān)正在運(yùn)行的功能的執(zhí)行過(guò)程的信息存儲(chǔ)在其執(zhí)行上下文中。

          執(zhí)行上下文是一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu),它包含關(guān)于函數(shù)執(zhí)行的詳細(xì)信息:控制流現(xiàn)在的位置、當(dāng)前變量、該變量的值(我們?cè)谶@里不使用它)和很少的其他內(nèi)部細(xì)節(jié)

          一個(gè)函數(shù)調(diào)用只有一個(gè)與之相關(guān)的執(zhí)行上下文。

          當(dāng)一個(gè)函數(shù)進(jìn)行嵌套調(diào)用時(shí),會(huì)發(fā)生以下情況:

          • 當(dāng)前函數(shù)暫停。
          • 與它相關(guān)的執(zhí)行上下文被保存在一個(gè)特殊的數(shù)據(jù)結(jié)構(gòu)中,稱為執(zhí)行上下文堆棧。
          • 執(zhí)行嵌套調(diào)用。
          • 在它結(jié)束后,從堆棧中檢索舊的執(zhí)行上下文,外部函數(shù)從停止的地方恢復(fù)。

          讓我們看看pow(2,3)調(diào)用過(guò)程中發(fā)生了什么。

          pow(2, 3)

          在調(diào)用pow(2,3)的開始,執(zhí)行上下文將存儲(chǔ)變量:x = 2, n = 3,執(zhí)行流在函數(shù)的第1行。

          我們可以把它概括為:

          Context:?{?x:?2,?n:?3,?at?line?1?}?call:?pow(2,?3)

          這時(shí)函數(shù)開始執(zhí)行,如果 n == 1 是假的,所以流繼續(xù)進(jìn)入if的第二個(gè)分支:

          function?pow(x,?n)?{
          ??if?(n?==?1)?{
          ????return?x;
          ??}?else?{
          ????return?x?*?pow(x,?n?-?1);
          ??}
          }

          alert(?pow(2,?3)?);

          變量是相同的,但是換行了,所以上下文現(xiàn)在是:

          Context:?{?x:?2,?n:?3,?at?line?5?}?call:?pow(2,?3)

          計(jì)算x * power (x, n - 1),我們需要用新的參數(shù)power(2,2)對(duì)power進(jìn)行子調(diào)用。

          pow(2, 2)

          執(zhí)行嵌套調(diào)用時(shí),JavaScript會(huì)在執(zhí)行上下文棧中記住當(dāng)前的執(zhí)行上下文。

          我們稱這個(gè)函數(shù)為pow,但這完全不重要。所有函數(shù)的過(guò)程都是一樣的:

          • 當(dāng)前上下文被“記住”在堆棧的頂部。

          • 為子調(diào)用創(chuàng)建新的上下文。

          • 當(dāng)子調(diào)用完成時(shí)——前一個(gè)上下文從堆棧中彈出,并繼續(xù)執(zhí)行。

          下面是我們進(jìn)入子調(diào)用pow(2,2)時(shí)的上下文堆棧:

          Context:?{?x:?2,?n:?2,?at?line?1?}?call:?pow(2,?2)
          Context:?{?x:?2,?n:?3,?at?line?5?}?call:?pow(2,?3)

          新的當(dāng)前執(zhí)行上下文位于頂部(和粗體),前面記住的上下文位于下面。

          當(dāng)我們完成子調(diào)用時(shí),很容易恢復(fù)前面的上下文,因?yàn)樗A袅藘蓚€(gè)變量和它停止的代碼的確切位置。

          pow(2, 1

          過(guò)程重復(fù):在第5行進(jìn)行新的子調(diào)用,現(xiàn)在參數(shù)x=2, n=1。

          一個(gè)新的執(zhí)行上下文被創(chuàng)建,之前的執(zhí)行上下文被壓入棧頂:

          Context:?{?x:?2,?n:?1,?at?line?1?}?call:?pow(2,?1)
          Context:?{?x:?2,?n:?2,?at?line?5?}?call:?pow(2,?2)

          現(xiàn)在有2個(gè)舊的上下文,1個(gè)正在運(yùn)行pow(2,1)。

          The exit

          在執(zhí)行pow(2,1)時(shí),與之前不同,條件n == 1是真實(shí)的,因此if的第一個(gè)分支工作:

          function?pow(x,?n)?{
          ??if?(n?==?1)?{
          ????return?x;
          ??}?else?{
          ????return?x?*?pow(x,?n?-?1);
          ??}
          }

          沒有更多的嵌套調(diào)用,因此函數(shù)完成,返回2。

          當(dāng)函數(shù)結(jié)束時(shí),不再需要它的執(zhí)行上下文,因此它被從內(nèi)存中刪除。前一個(gè)被從棧頂恢復(fù):

          Context:?{?x:?2,?n:?2,?at?line?5?}?call:?pow(2,?2)
          Context:?{?x:?2,?n:?3,?at?line?5?}?call:?pow(2,?3)

          pow(2,2)的執(zhí)行重新開始。它有子調(diào)用pow(2,1)的結(jié)果,所以它也可以完成x * pow(x, n - 1)的求值,返回4。

          然后恢復(fù)之前的上下文:

          Context:?{?x:?2,?n:?3,?at?line?5?}?call:?pow(2,?3)

          當(dāng)它完成時(shí),我們得到pow(2,3) = 8的結(jié)果。

          在這種情況下,遞歸深度是:3。

          從上面的例子中可以看出,遞歸深度等于堆棧中上下文的最大數(shù)量。

          注意內(nèi)存要求。上下文需要內(nèi)存。在我們的例子中,n的冪實(shí)際上需要n個(gè)上下文的內(nèi)存,對(duì)于所有n的較小值。

          基于循環(huán)的算法更節(jié)省內(nèi)存:

          function?pow(x,?n)?{
          ??let?result?=?1;

          ??for?(let?i?=?0;?i?????result?*=?x;
          ??}

          ??return?result;
          }



          瀏覽 15
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花一区在线视频观看 | 国产一级A片视频 | 美女视频黄8视频大全 | 欧美成人三级在线 | 亚洲视频app |