查看 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);
因此,我们可以清楚地看到,在呼叫堆栈大小中也考虑了区域变量的数量(即区域变量的存储器)。如果有很多区域变量,那么没有。递回呼叫的次数会更少。
编辑:我们都知道堆栈大小会因浏览器而异。所以输出在不同的浏览器中不会相同,但在同一个浏览器中应该是一致的,即使我们多次运行它。
希望现在一切都说得通。
0 评论