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);

另見