我有以下代码示例来说明我的观点。当我在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>
答案 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.你的调用堆栈限制会受到很大影响通过围绕函数的类结构,即使它们不是传统上认为是函数堆栈的单独级别。