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

使用Javascript类函数进行15次递归后出现堆栈溢出,javascript,class,recursion,stack-overflow,stackpanel,Javascript,Class,Recursion,Stack Overflow,Stackpanel,我有下面的代码示例来说明我的观点。当我在Vista的IE8中加载它时,我得到一个错误“Stack Overfow at line:16” 如果我使用顶级函数(在testClass对象之外)递归,我可以在没有堆栈溢出的情况下递归数百万次 为什么会这样?最终我只是实现了一个函数Que,而不是使用递归,但对我来说没有意义,我想了解原因 --代码-- 复发试验 函数testClass(){ 这个.x=15; this.recurse=函数(){ 这是一本书; this.recurse(); } } v

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

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

为什么会这样?最终我只是实现了一个函数Que,而不是使用递归,但对我来说没有意义,我想了解原因

--代码--


复发试验
函数testClass(){
这个.x=15;
this.recurse=函数(){
这是一本书;
this.recurse();
}
}
var wtf=newtestclass();
recurse();
警报(“完成”);

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

看来你想要


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

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

            alert('done');

好的,下面是我对这个问题的一些更深入的了解。在回去修复我认为是我的应用程序的问题之后,我仍然有这个问题。促使我继续研究这个问题的原因是,如果我只重复14次,它就会成功完成

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

第二,我的代码结构如下:

-HTA

--编辑类

---DivManagerClass

----键绑定类

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

在我的KeyBindingClass中,我有一个repeater属性,如果按下数字修饰符,它将重复上一次击键N次。对于不知道的用户,在vim的视觉模式下按“3”和“x”键将删除三个字符

在我使用大于14的数字修饰符之前,一切都正常

我一直试图用一个小的测试工具重现这个问题,但没有成功。在一个基本的测试工具中,我能够递归多达3000次。所以我开始尽我所能重新创建场景。首先,我将对recurse方法的调用移动到另一个类/方法中。这将我的调用堆栈限制在1600左右(几乎一半的堆栈消失了)

然后,我将jQuery添加到混合中,并将对ParentClass.recurse方法的调用移动到document.onready jQuery处理程序中的keybinding事件中。这使我的呼叫量减少到1300左右

然后,我将我的代码移动到一个HTA中,它再次将我的调用堆栈一分为二!在尽可能快地模仿我的代码库之后,我得到了大约515个调用堆栈

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

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


我仍然可以使用函数队列来解决我的问题,但我只是想让其他人知道a.我不会将如此简单的问题发布到堆栈溢出,B.调用堆栈限制可能会受到函数周围的类结构的极大影响,尽管它们不是你通常认为的函数栈的不同层次。

好吧,这是我的一个错误,我简化了一个复杂的类用于演示目的,我忘了包括这一点。见下面我的答案。在我的实际代码库中,我能够在没有SO的情况下递归14次,但在15次时它将失败。

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

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

            alert('done');