|
1 | 1 | ---
|
2 | 2 | title: "InternalError: too much recursion"
|
3 | 3 | slug: Web/JavaScript/Reference/Errors/Too_much_recursion
|
| 4 | +l10n: |
| 5 | + sourceCommit: 6d606174faaedaa5dee7b7ebd87602cd51e5dd7e |
4 | 6 | ---
|
5 | 7 |
|
6 | 8 | {{jsSidebar("Errors")}}
|
7 | 9 |
|
| 10 | +當函式呼叫過多,或函式缺少基礎情況時,會發生 JavaScript 的「too much recursion」或「Maximum call stack size exceeded」例外。 |
| 11 | + |
8 | 12 | ## 訊息
|
9 | 13 |
|
10 | 14 | ```plain
|
11 |
| -InternalError: too much recursion |
| 15 | +RangeError: Maximum call stack size exceeded (Chrome) |
| 16 | +InternalError: too much recursion (Firefox) |
| 17 | +RangeError: Maximum call stack size exceeded. (Safari) |
12 | 18 | ```
|
13 | 19 |
|
14 | 20 | ## 錯誤類型
|
15 | 21 |
|
16 |
| -{{jsxref("InternalError")}} |
| 22 | +Firefox 中為 {{jsxref("InternalError")}};Chrome 和 Safari 中為 {{jsxref("RangeError")}}。 |
| 23 | + |
| 24 | +## 哪裡出錯了? |
17 | 25 |
|
18 |
| -## 哪裡錯了? |
| 26 | +一個會呼叫自己的函式稱為*遞迴函式*。一旦滿足某個條件,函式就會停止呼叫自己。這稱為*基礎情況*。 |
19 | 27 |
|
20 |
| -一個呼叫自己的函式稱為*遞迴函式*(recursive function)。在某些方面,遞迴和迴圈很像。它們都需要在指定條件(以避免無窮迴圈,或是本例的無窮遞迴)下,重複執行數次相同的程式碼。如果遞迴執行太多次、或成為無窮遞迴的話,JavaScript 就會出現這個錯誤。 |
| 28 | +在某些方面,遞迴類似於迴圈。兩者都會多次執行相同的程式碼,且都需要一個條件(以避免無限迴圈,或在此情況下是無限遞迴)。當函式呼叫過多,或函式缺少基礎情況時,JavaScript 就會拋出此錯誤。 |
21 | 29 |
|
22 |
| -## 實例 |
| 30 | +## 範例 |
23 | 31 |
|
24 |
| -以下的遞迴函式,會根據終止條件,而運行十次。 |
| 32 | +此遞迴函式根據終止條件執行 10 次。 |
25 | 33 |
|
26 | 34 | ```js
|
27 | 35 | function loop(x) {
|
28 | 36 | if (x >= 10)
|
29 |
| - // "x >= 10" 是終止條件 |
| 37 | + // 「x >= 10」是終止條件 |
30 | 38 | return;
|
31 |
| - // do stuff |
| 39 | + // 做些事情 |
32 | 40 | loop(x + 1); // 遞迴呼叫
|
33 | 41 | }
|
34 | 42 | loop(0);
|
35 | 43 | ```
|
36 | 44 |
|
37 |
| -如果把終止條件的次數設得太高,函式就不會運作了: |
| 45 | +將此條件設定為一個極高的值,將無法運作: |
38 | 46 |
|
39 | 47 | ```js example-bad
|
40 | 48 | function loop(x) {
|
41 | 49 | if (x >= 1000000000000) return;
|
42 |
| - // do stuff |
| 50 | + // 做些事情 |
43 | 51 | loop(x + 1);
|
44 | 52 | }
|
45 | 53 | loop(0);
|
46 | 54 |
|
47 | 55 | // InternalError: too much recursion
|
48 | 56 | ```
|
49 | 57 |
|
| 58 | +這個遞迴函式缺少一個基礎情況。由於沒有終止條件,函式將會無限地呼叫自己。 |
| 59 | + |
| 60 | +```js example-bad |
| 61 | +function loop(x) { |
| 62 | + // 缺少基礎情況 |
| 63 | + loop(x + 1); // 遞迴呼叫 |
| 64 | +} |
| 65 | + |
| 66 | +loop(0); |
| 67 | + |
| 68 | +// InternalError: too much recursion |
| 69 | +``` |
| 70 | + |
| 71 | +### Class 錯誤:遞迴過多 |
| 72 | + |
| 73 | +```js example-bad |
| 74 | +class Person { |
| 75 | + constructor() {} |
| 76 | + set name(name) { |
| 77 | + this.name = name; // 遞迴呼叫 |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +const tony = new Person(); |
| 82 | +tony.name = "Tonisha"; // InternalError: too much recursion |
| 83 | +``` |
| 84 | + |
| 85 | +當一個值被指派給 name 屬性(this.name = name;)時,JavaScript 需要設定該屬性。當這種情況發生時,就會觸發 setter 函式。 |
| 86 | + |
| 87 | +在此範例中,當 setter 被觸發時,它被告知要再次做同樣的事情:_設定它本應處理的同一個屬性_。這會導致函式不斷地呼叫自己,從而造成無限遞迴。 |
| 88 | + |
| 89 | +如果在 getter 中使用相同的變數,也會出現此問題。 |
| 90 | + |
| 91 | +```js example-bad |
| 92 | +class Person { |
| 93 | + get name() { |
| 94 | + return this.name; // 遞迴呼叫 |
| 95 | + } |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +為避免此問題,請確保在 setter 函式內部指派的屬性與最初觸發 setter 的屬性不同。getter 也是如此。 |
| 100 | + |
| 101 | +```js |
| 102 | +class Person { |
| 103 | + constructor() {} |
| 104 | + set name(name) { |
| 105 | + this._name = name; |
| 106 | + } |
| 107 | + get name() { |
| 108 | + return this._name; |
| 109 | + } |
| 110 | +} |
| 111 | +const tony = new Person(); |
| 112 | +tony.name = "Tonisha"; |
| 113 | +console.log(tony); |
| 114 | +``` |
| 115 | + |
50 | 116 | ## 參見
|
51 | 117 |
|
52 |
| -- {{Glossary("Recursion")}} |
53 |
| -- [遞迴函式](/zh-TW/docs/Web/JavaScript/Guide/Functions#recursion) |
| 118 | +- {{Glossary("Recursion", "遞迴")}} |
| 119 | +- [遞迴函式](/zh-TW/docs/Web/JavaScript/Guide/Functions#遞迴) |
0 commit comments