InternalError: too much recursion
当函数调用过多,或函数缺少基本情况时,会发生 JavaScript 异常“递归过多”或“超出最大调用堆栈大小”。
消息
RangeError: Maximum call stack size exceeded (Chrome) InternalError: too much recursion (Firefox) RangeError: Maximum call stack size exceeded. (Safari)
错误类型
Firefox 中的 InternalError;Chrome 和 Safari 中的 RangeError。
哪里出错了?
调用自身的函数称为递归函数。一旦满足条件,函数就会停止调用自身。这称为基本情况。
在某些方面,递归类似于循环。两者都多次执行相同的代码,并且都需要一个条件(以避免无限循环,或者在这种情况下是无限递归)。当函数调用过多,或函数缺少基本情况时,JavaScript 将抛出此错误。
示例
根据退出条件,此递归函数运行 10 次。
js
function loop(x) {
if (x >= 10)
// "x >= 10" is the exit condition
return;
// do stuff
loop(x + 1); // the recursive call
}
loop(0);
将此条件设置为极高值将不起作用
js
function loop(x) {
if (x >= 1000000000000) return;
// do stuff
loop(x + 1);
}
loop(0);
// InternalError: too much recursion
此递归函数缺少基本情况。由于没有退出条件,函数将无限期地调用自身。
js
function loop(x) {
// The base case is missing
loop(x + 1); // Recursive call
}
loop(0);
// InternalError: too much recursion
类错误:递归过多
js
class Person {
constructor() {}
set name(name) {
this.name = name; // Recursive call
}
}
const tony = new Person();
tony.name = "Tonisha"; // InternalError: too much recursion
当一个值被赋给属性名 (this.name = name;) 时,JavaScript 需要设置该属性。发生这种情况时,会触发 setter 函数。
在此示例中,当 setter 被触发时,它被告知再次执行相同的操作:设置它应该处理的同一属性。这导致函数一次又一次地调用自身,使其无限递归。
如果 getter 中使用了相同的变量,也会出现此问题。
js
class Person {
get name() {
return this.name; // Recursive call
}
}
为避免此问题,请确保 setter 函数内部赋值的属性与最初触发 setter 的属性不同。getter 也是如此。
js
class Person {
constructor() {}
set name(name) {
this._name = name;
}
get name() {
return this._name;
}
}
const tony = new Person();
tony.name = "Tonisha";
console.log(tony);