此頁面由社群從英文翻譯而來。了解更多並加入 MDN Web Docs 社群。
InternalError: too much recursion
當函式呼叫過多,或函式缺少基礎情況時,會發生 JavaScript 的「too much recursion」或「Maximum call stack size exceeded」例外。
In this article
訊息
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」是終止條件 return; // 做些事情 loop(x + 1); // 遞迴呼叫}loop(0);將此條件設定為一個極高的值,將無法運作:
js
function loop(x) { if (x >= 1000000000000) return; // 做些事情 loop(x + 1);}loop(0);// InternalError: too much recursion這個遞迴函式缺少一個基礎情況。由於沒有終止條件,函式將會無限地呼叫自己。
js
function loop(x) { // 缺少基礎情況 loop(x + 1); // 遞迴呼叫}loop(0);// InternalError: too much recursionClass 錯誤:遞迴過多
js
class Person { constructor() {} set name(name) { this.name = name; // 遞迴呼叫 }}const tony = new Person();tony.name = "Tonisha"; // InternalError: too much recursion當一個值被指派給 name 屬性(this.name = name;)時,JavaScript 需要設定該屬性。當這種情況發生時,就會觸發 setter 函式。
在此範例中,當 setter 被觸發時,它被告知要再次做同樣的事情:設定它本應處理的同一個屬性。這會導致函式不斷地呼叫自己,從而造成無限遞迴。
如果在 getter 中使用相同的變數,也會出現此問題。
js
class Person { get name() { return this.name; // 遞迴呼叫 }}為避免此問題,請確保在 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);