javascript/nodeJs 中的两个递归函数和计算器错误。了解差异
Two recursive functions and stackoverflow errors in javascript/nodeJs. Understanding the differences
查看 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 中引发堆栈溢出
I gave the below answer in error, I got mixed up about which function was throwing the exception. Please ignore.
你的第一个函数能够利用尾调用优化,而你的第二个函数不能(或者是,但可能不是以 node.js 语言实现的方式)。
考虑一下:您的第一个函数的通常条件是它以 return sumAll(n, i + 1, i + result)
结尾,这意味着一旦您得到 return 的内容,您就可以 return 那个。
然而,您的第二个函数以 return n* factorial((n-1))
结尾,这意味着一旦您得到 return 的内容,您必须对其执行另一项操作(将其乘以 n),然后才能真正 return结果。
我相信 node.js 解释器无法尾调用优化第二个函数,因为它需要在 return.
之前对其执行另一个操作
请注意:我不确定这就是答案,而且我怀疑 node.js 可能不支持任何类型的尾调用优化。这是我的理论,但关于为什么一个函数可能会以这种方式出错而另一个函数不会。
局部变量的数量(即局部变量的内存)也在调用堆栈大小中考虑。
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);
因此,我们可以清楚地看到调用堆栈大小也考虑了局部变量的数量(即局部变量的内存)。如果有很多局部变量,那么没有。递归调用的次数会更少。
编辑:我们都知道堆栈大小会因浏览器而异。所以输出在不同的浏览器中不会相同,但在同一个浏览器中应该是一致的,即使我们 运行 它多次。
希望现在一切都有意义。
查看 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 中引发堆栈溢出
I gave the below answer in error, I got mixed up about which function was throwing the exception. Please ignore.
你的第一个函数能够利用尾调用优化,而你的第二个函数不能(或者是,但可能不是以 node.js 语言实现的方式)。
考虑一下:您的第一个函数的通常条件是它以 return sumAll(n, i + 1, i + result)
结尾,这意味着一旦您得到 return 的内容,您就可以 return 那个。
然而,您的第二个函数以 return n* factorial((n-1))
结尾,这意味着一旦您得到 return 的内容,您必须对其执行另一项操作(将其乘以 n),然后才能真正 return结果。
我相信 node.js 解释器无法尾调用优化第二个函数,因为它需要在 return.
之前对其执行另一个操作请注意:我不确定这就是答案,而且我怀疑 node.js 可能不支持任何类型的尾调用优化。这是我的理论,但关于为什么一个函数可能会以这种方式出错而另一个函数不会。
局部变量的数量(即局部变量的内存)也在调用堆栈大小中考虑。
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);
因此,我们可以清楚地看到调用堆栈大小也考虑了局部变量的数量(即局部变量的内存)。如果有很多局部变量,那么没有。递归调用的次数会更少。
编辑:我们都知道堆栈大小会因浏览器而异。所以输出在不同的浏览器中不会相同,但在同一个浏览器中应该是一致的,即使我们 运行 它多次。
希望现在一切都有意义。