递归 - 测试最大堆栈大小时调用堆栈无法弹出

时间:2016-04-26 16:50:26

标签: javascript callstack event-loop

基本上 调用堆栈 会在开始逐个弹出 调用函数 last-in 函数调用返回。但是当我尝试创建一个接近其最大值的调用堆栈时, uncaught expression 就会被提升。

//Code for testing the stack size
var cnt = 0;

function test(){
 //Max stack size is nearer to ~41800
 if(cnt++ == 41763){
  console.log('finished');
  return true;
 }
 return test();
}

test();

所以上面的代码在 chromium Version 49.0.2623.112 m 中给我一个例外,如下所示,

  

未捕获的异常

     

<真

请注意,上述错误中没有消息。我的问题是,

堆栈中的最后一个函数调用已返回true,这意味着未超出堆栈大小。为什么没有返回该堆栈中的其他函数调用?这个空白异常消息的原因是什么?

2 个答案:

答案 0 :(得分:8)

这里的问题是

console.log('finished');

这会给调用堆栈添加一些额外的函数,这些函数会超出限制,但是通过异常处理,你的代码无论如何都会被执行。

尝试在没有console.log的情况下运行它,你会发现你达到了极限,看到了真或异。

答案 1 :(得分:3)

console.log不符合javascript规范,因此行为未定义,可以从发行版更改为发行版。所以你的版本中发生的事情可能不会发生在我们的版本中。

以下是对发生的事情最可能的解释:可以肯定的是,console.log会增加堆栈的大小,因为是在返回之前调用的最后一个语句,它有时会生成Maximum call stack你非常接近极限。最大调用可以在console.log代码(调用其他内容)中发生,以及此错误将如何处理它,它取决于console.log的代码。看起来console.log中的代码在发生错误时会抛出Uncaught异常。现在,当您尝试使用try时出现错误时,代码会继续,这就是出现真实的原因。

以下是jsfiddle中的示例,其中我覆盖了console.log,结果显示在HTML中。您可以通过删除console.log的覆盖代码来查看事情的变化。试试这个并告诉我们结果是否再次变得奇怪。

值得注意的是,当出现Maximum call stack size exceeded错误时,它也取决于堆栈帧的大小(局部变量)。

注意:在ECMAScript 6 spec中,如果函数调用是函数中的最后一个操作,它将不会进入堆栈,但它将“立即”运行,因此您的代码将运行而不会出现错误所有数字,无论你输入什么数字。