全局变量值在堆栈超过node.js中的无限远程递归后神秘地重置

时间:2011-07-28 15:47:59

标签: javascript recursion node.js stack global-variables

我想使用全局值递增计算node.js(v0.4.10)中无限递归函数的步骤。但是,计数总是假装为零

> c = 0
> (function f() { c++; console.log(c); f() })();
1
2
...
18648
RangeError: Maximum call stack size exceeded
> c 
0

从函数中将c值记录到控制台显示该值实际上是递增的,但不知何故,它最终会在该堆栈事故后重置。即使使用global.c而不是c

这是正确的行为吗?这里发生了什么?例如在铬(v14)中,c按预期保留最终计数。

更新

事实证明,上述仅在交互模式下有效。当代码从文件执行,并且函数包含在try-catch块中(以防止过早退出)时,c值是正确的。

c = 0;
try {
  (function f() { c++; f() })();
} catch(e) {};
console.log(c);

然而,交互式node.js和chromium javascript控制台之间存在差异,其中值存在未处理的异常

1 个答案:

答案 0 :(得分:2)

每个交互模式的行为都与JavaScript文件的标准执行略有不同(Isaac Schlueter在某处写道:“我从未见过一个没有至少一点点魔法的REPL < / em>的“)。交互模式必须评估文本,该文本通常在不同的上下文中运行代码。

在Node.JS的情况下,每个命令都在自己的上下文中执行,然后REPL会注意返回结果。如果由于某些错误导致命令失败,则变量的值保持不变(因为在执行的上下文中已更改的变量'die')。当我们运行JavaScript文件标准方式时,我们没有这个单独的执行上下文,我们直接更改我们的变量。

您可以更改示例以手动创建错误并发挥作用:

c=0;
(function f(x){ c++; if(x) f(x-1); else throw new Error();  })(10);

只要代码执行错误,c的最终值在REPL中将为0。由于错误,REPL无法将c的全局值更新为在测试函数的执行上下文中计算的值。