使用Javascript类函数进行15次递归后的堆栈溢出

时间:2009-10-08 18:36:09

标签: javascript class recursion stack-overflow stackpanel

我有以下代码示例来说明我的观点。当我在Vista上的IE8中加载它时,我收到错误“Stack Overfow at line:16”

如果我使用顶级函数(在testClass对象之外)递归,我可以在没有堆栈溢出的情况下递归数百万次。

为什么会这样?最后我只是实现了一个函数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>

2 个答案:

答案 0 :(得分:7)

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

看起来你想......


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

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

            alert('done');

答案 1 :(得分:1)

好的,这里有一些关于我遇到的问题的更多见解。回过头来修复我认为是我的应用程序的问题后,我仍然遇到了问题。让我追究这个问题的那个部分是,如果我只复制了14次,它就会成功完成。

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

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

-HTA

- EditorClass

--- DivManagerClass

---- KeyBindingClass

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

在我的KeyBindingClass中,我有一个转发器属性,如果按下数字修饰符,它将重复最后一次键击N次。对于那些不知道在vim中以视觉模式按键“3”和“x”的人将删除三个字符。

一切正常,直到我使用大于14的数字修饰符。

我一直试图用小型测试工具重现这个问题而不能。我能够在一个基本的测试工具中增加到3000。所以我开始尽可能地重新创建场景。首先,我将调用recurse方法转移到另一个类/方法中。这限制了我的调用堆栈到1600左右(几乎一半的堆栈消失了。)

然后我将jQuery添加到混合中并将对ParentClass.recurse方法的调用移动到document.onready jquery处理程序内的键绑定事件中。这使我的筹码减少到1300左右。

然后我将我的代码移动到HTA中,再次将我的调用堆栈减半!在尽可能地模仿我的代码库之后,我尽可能快地达到了大约515的callstack。

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

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

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