查看 SICP 書和 JS 函式式編程,我創建了兩個遞回函式。我的期望是它們都引發了堆疊溢位錯誤。但只有 sumAll() 函式引發了錯誤。請參閱下面兩個函式 sumAll() 和 factorial() 的代碼:
正如預期的那樣, sumAll() 函式確實引發了堆疊溢位錯誤
function sumAll(n, i = 0, result = 0) {
return (i > n)
? result
: sumAll(n, i 1, i result);
}
console.log(sumAll(10000));
下面的 factorial() 函式沒有引發堆疊溢位錯誤:
function factorial(n){
return (n == 1)
? 1
: n* factorial((n-1))
}
console.log(factorial(10000))
我的問題是為什么 factorial() 函式不會引發堆疊溢位并且在 nodeJS 中完美運行,同時 sumAll() 確實在 nodeJS 中也引發了它
uj5u.com熱心網友回復:
我錯誤地給出了以下答案,我對哪個函式拋出例外感到困惑。請忽略。
您的第一個函式能夠利用尾呼叫優化,而您的第二個函式不是(或者它是,但可能不是以 node.js 語言實作的方式)。
考慮一下:你的第一個函式的通常條件是它以 結尾return sumAll(n, i 1, i result),這意味著一旦你得到一些要回傳的東西,你就可以回傳它。
但是return n* factorial((n-1)),您的第二個函式以 結尾,這意味著一旦您要回傳某些內容,就必須對其進行 ANOTHER 操作(將其乘以 n),然后才能實際回傳結果。
我相信 node.js 解釋器無法對第二個函式進行尾呼叫優化,因為它需要在回傳之前對其執行另一個操作。
請注意:我不確定這是不是答案,并且我懷疑 node.js 可能不支持任何型別的尾呼叫優化。這是我的理論,但為什么一個函式可能會以這種方式出錯而另一個函式不會。
uj5u.com熱心網友回復:
在呼叫堆疊大小中也考慮了區域變數的數量(即區域變數的記憶體)。
function computeMaxCallStackFrames(a, b, c, d) {
try {
return 1 computeMaxCallStackFrames(a 1, b 1, c 2, d 3);
} catch (e) {
// Call stack overflow
// console.log(e);
return 1;
}
}
var stackFrames = computeMaxCallStackFrames(1, 4, 6, 2);
console.log(stackFrames);
嘗試增加編號。的引數,你會看到遞回呼叫/呼叫堆疊幀的數量減少。
function computeMaxCallStackFrames(a, b, c, d, e) {
try {
return 1 computeMaxCallStackFrames(a 1, b 1, c 2, d 3, e-2);
} catch (e) {
// Call stack overflow
// console.log(e);
return 1;
}
}
var stackFrames = computeMaxCallStackFrames(1, 4, 6, 2, 9);
console.log(stackFrames);
零區域變數。
function computeMaxCallStackFrames() {
try {
return 1 computeMaxCallStackFrames();
} catch (e) {
// Call stack overflow
// console.log(e);
return 1;
}
}
var stackFrames = computeMaxCallStackFrames();
console.log(stackFrames);
因此,我們可以清楚地看到,在呼叫堆疊大小中也考慮了區域變數的數量(即區域變數的記憶體)。如果有很多區域變數,那么沒有。遞回呼叫的次數會更少。
編輯:我們都知道堆疊大小會因瀏覽器而異。所以輸出在不同的瀏覽器中不會相同,但在同一個瀏覽器中應該是一致的,即使我們多次運行它。
希望現在一切都說得通。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/406392.html
標籤:
