内部错误:太多的递归

当函数调用过多或函数缺少基本情况时,会发生 JavaScript 异常 "太多的递归" 或 "超出最大调用堆栈大小"。

¥The JavaScript exception "too much recursion" or "Maximum call stack size exceeded" occurs when there are too many function calls, or a function is missing a base case.

信息

¥Message

RangeError: Maximum call stack size exceeded (Chrome)
InternalError: too much recursion (Firefox)
RangeError: Maximum call stack size exceeded. (Safari)

错误类型

¥Error type

Firefox 中的 InternalError;Chrome 和 Safari 中的 RangeError

¥InternalError in Firefox; RangeError in Chrome and Safari.

什么地方出了错?

¥What went wrong?

调用自身的函数称为递归函数。一旦满足条件,该函数就会停止调用自身。这称为基本情况。

¥A function that calls itself is called a recursive function. Once a condition is met, the function stops calling itself. This is called a base case.

在某些方面,递归类似于循环。两者都多次执行相同的代码,并且都需要一个条件(以避免无限循环,或者更确切地说,在这种情况下避免无限递归)。当函数调用过多,或者函数缺少基本情况时,JavaScript 将抛出此错误。

¥In some ways, recursion is analogous to a loop. Both execute the same code multiple times, and both require a condition (to avoid an infinite loop, or rather, infinite recursion in this case). When there are too many function calls, or a function is missing a base case, JavaScript will throw this error.

示例

¥Examples

根据退出条件,此递归函数运行 10 次。

¥This recursive function runs 10 times, as per the exit condition.

js
function loop(x) {
  if (x >= 10)
    // "x >= 10" is the exit condition
    return;
  // do stuff
  loop(x + 1); // the recursive call
}
loop(0);

将此条件设置为极高的值将不起作用:

¥Setting this condition to an extremely high value, won't work:

js
function loop(x) {
  if (x >= 1000000000000) return;
  // do stuff
  loop(x + 1);
}
loop(0);

// InternalError: too much recursion

该递归函数缺少基本情况。由于没有退出条件,该函数将无限地调用自身。

¥This recursive function is missing a base case. As there is no exit condition, the function will call itself infinitely.

js
function loop(x) {
  // The base case is missing
  loop(x + 1); // Recursive call
}

loop(0);

// InternalError: too much recursion

类错误:太多的递归

¥Class error: 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 函数就会被触发。

¥When a value is assigned to the property name (this.name = name;) JavaScript needs to set that property. When this happens, the setter function is triggered.

在此示例中,当触发 setter 时,它被告知再次执行相同的操作:设置它要处理的相同属性。这会导致函数一次又一次地调用自身,从而使其无限递归。

¥In this example when the setter is triggered, it is told to do the same thing again: to set the same property that it is meant to handle. This causes the function to call itself, again and again, making it infinitely recursive.

如果在 getter 中使用相同的变量,也会出现此问题。

¥This issue also appears if the same variable is used in the getter.

js
class Person {
  get name() {
    return this.name; // Recursive call
  }
}

为了避免此问题,请确保分配给 setter 函数内部的属性与最初触发 setter 的属性不同。getter 也是如此。

¥To avoid this problem, make sure that the property being assigned to inside the setter function is different from the one that initially triggered the setter. The same goes for the 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);

也可以看看