2009-10-08 59 views
0

我有以下代码示例来说明我的观点。当我加载此在IE8在Vista上我得到的错误“堆栈Overfow在行:16”使用Javascript类函数执行15次递归后的堆栈溢出

如果我改乘使用顶级函数(TestClass的对象外)我可以递归数百万次无堆栈溢出。

这是怎么发生的?最终,我只是实现了一个Function Que,而不是使用递归,但对我来说没有意义,我想了解原因。

- 代码 -

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"> 
<html> 
    <head> 
     <title>Recusion Test</title> 
     <body> 
     </body> 

     <script type="text/javascript"> 

      function testClass() { 
       this.x = 15; 
       this.recurse = function() { 
        this.x--; 
        this.recurse(); 
       } 
      } 

      var wtf = new testClass(); 
       wtf.recurse(); 

      alert('done'); 
     </script> 
    </head> 
</html> 
+0

好的,这是我的一个错误,我简化了一个复杂的类用于演示目的,我忘了包括它。请参阅下面的答案。在我的实际代码库中,我能够在没有SO的情况下递归14次,但在15时它会失败。 – 2009-10-08 21:29:05

回答

7

没有为您的递归语句,因此它会永远运行没有终止条件。

看样子,你想...


      function testClass() { 
       this.x = 15; 
       this.recurse = function() { 
        if (this.x--) 
         this.recurse(); 
       } 
      } 

      var wtf = new testClass(); 
       wtf.recurse(); 

      alert('done'); 
1

好吧,这里的一些更深入地了解我是有这个问题。在回到我的应用程序并修复了我认为的问题后,我仍然遇到了这个问题。让我追求这个问题的部分是,如果我递归只有14次,它会成功完成。

首先,我在HTA中执行原始代码,而不是Internet Explorer。我正在编写一个类似于FCKEditor的基于VIM的代码编辑器。

其次,我的代码的结构如下:

-HTA

--EditorClass

--- DivManagerClass

---- KeyBindingClass

在我的KeyBindingClass我有一个类似于提供的例子的代码库(除了它有一个终止条件)

在我的KeyBindingClass中,我有一个repeater属性,如果按下数字修饰符,它将重复最后一次keystrok N次。对于那些不知道在vim中以可视模式按键'3'和'x'的人,会删除三个字符。直到我用一个数值修改超过14

我一直试图重现此问题的一个小测试工具,并不能

,一切运行良好。我能够在基本测试工具中递增到3000。所以我开始重新创建场景,尽我所能。首先,我将调用转移到另一个类/方法的递归方法。这限制了我的调用堆栈大约在1600左右(几乎一半的堆栈消失了)。

然后我将jQuery添加到混合中,并将调用移动到ParentClass.recurse方法中,并放入document.onready jquery handler中的键绑定事件。这减少了我的调用堆栈大约1300.

然后我将我的代码移到一个HTA中,将我的调用堆栈再次削减一半!尽可能地模仿我的代码库后,我可以尽可能快地到达大约515的调用堆栈。

在做了一些研究后,我发现IE使用可用的内存空间来确定调用堆栈的大小。我猜测HTA在这方面有点严格。我还没有弄清楚在给定类结构的情况下,其他因素限制了我的应用程序到如此低的调用堆栈,但这绝对是代码结构。

我可以将我的基本递归测试放在顶层执行脚本标记中,并在达到堆栈溢出之前获得大约1473个调用。

我仍然可以使用函数队列来解决我的问题,但我只是想让其他人知道答:我不会在Stack Overflow中发布这样一个简单的问题,并且B.您的调用堆栈限制可能会很大受到围绕函数的类结构的影响,即使它们不是传统上认为函数堆栈的单独级别。