2016-01-28 94 views
-3

我想使用非遞歸方法重複調用一個函數。我有一個非遞歸方法,下面的例子:在javascript中使用函數堆棧調用非遞歸方法

function foo(i) { 
 
    if (i < 0) 
 
    return; 
 

 
    console.log('begin:' + i); 
 
    foo(i - 1); 
 
    console.log('end:' + i); 
 
} 
 

 
foo(3);
<!-- this is to make console output visible --> 
 
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

,它提供了以下的輸出:

begin:3 
begin:2 
begin:1 
begin:0 
end:0 
end:1 
end:2 
end:3 

任何人可以讓我明白爲什麼它打印以下幾行:

end:0 
end:1 
end:2 
end:3 

Ev從函數foo(i - 1);返回

+8

這是一個遞歸函數............... –

+4

你爲什麼認爲它是非遞歸的? – hindmost

+0

https://developer.mozilla。org/en-US/docs/Web/JavaScript/Guide/Functions –

回答

0

好吧,它是一個遞歸函數,因爲函數在其定義塊中調用自己。

foo(3) : ['begin:3', foo(2), 'end:3'] 
foo(2) : ['begin:2', foo(1), 'end:2'] 
foo(1) : ['begin:1', foo(0), 'end:1'] 
foo(0) : ['begin:0', foo(-1), 'end:0'] 
foo(-1) : [] 

如果你把它放在一起,你有你描述的輸出。想象一下,它像一個matryoshka doll ......

讓檢查最後3條線(爲簡單起見,我省略了換行):

  • foo(-1)沒有給出輸出
  • foo(0)'begin:0' + foo(-1) + 'end:0'

    = begin:0 end:0

  • foo(1)給出'begin:1' + foo(0) + 'end:1'

    = begin:1 begin:0 end:0 end:1

+0

但它沒有打印開始:3end:3begin:2end:2 ......... ???/ –

+0

它以相反順序打印'end's。 – putvande

+0

@putvande:不,它不是......仔細看看這些元素是如何組裝成像一個matryoshka娃娃... – xmoex

0

的解決方案是使用一個處理隊列而不是函數調用堆棧。然後函數foo按順序調用,而不是遞歸調用。

var q=[3] 
function foo(x){ 
    ... 
    q[q.length] = x-1//instead of foo(x-1) 
    ... 
} 
while(q.length){foo(q.shift())} 
+1

這是一個答案?也許你應該解釋一下。 – putvande

2

因爲從頂部底部,執行的代碼,當你調用一個函數內部功能,這並不意味着該父功能的執行停止。它調用內部函數和內部函數調用內部函數等。直到最深函數返回值的時刻您的值爲最深函數的undefined

所以它打印

begin:3 
begin:2 
begin:1 
begin:0 

在這一點上最深的功能達到和它返回undefinedreturn;),它的上升,以前的功能未定義之前有i=0,這樣的函數執行完畢,並冒泡調用內部函數後執行其餘的代碼。結果:

end:0 
end:1 
end:2 
end:3