「例外(エラー)をデバッグする力」は、プログラミング初級から中級に進む大きなステップです。
ここでは、「stack(スタックトレース)」の見方と活用方法を、初心者でもわかるようにかみ砕いて解説します。
1. 「stack」とは? — エラーの“足あと”
プログラムがエラーを出したとき、
ブラウザのコンソールや Node.js ではこんな表示が出ます:
TypeError: Cannot read properties of undefined (reading 'length')
at countItems (main.js:5:18)
at processData (main.js:10:5)
at main (main.js:15:3)
これが「スタックトレース(stack trace)」です。
意味をかみ砕くと
これは「エラーが発生するまでに、どの関数がどの順番で呼ばれたか」を表す足あとです。
上の例を人間の言葉で読むとこうなります:
main() → processData() → countItems() の順で関数を呼んでいたら、
countItems()の 5行目18文字目でエラーが起きた。
2. 実際の例で確認してみよう
次のコードをブラウザのコンソールや Node.js で動かしてみてください:
function countItems(arr) {
return arr.length;
}
function processData(data) {
return countItems(data.items);
}
function main() {
const data = {}; // items プロパティがない!
console.log(processData(data));
}
main();
JavaScript実行結果(エラー表示):
TypeError: Cannot read properties of undefined (reading 'length')
at countItems (main.js:2:15)
at processData (main.js:6:10)
at main (main.js:10:3)
3. 読み方を分解してみよう
| 部分 | 意味 |
|---|---|
TypeError | エラーの種類(型に関するエラー) |
Cannot read properties of undefined | 原因(undefined からプロパティを読もうとした) |
(reading 'length') | どのプロパティだったか(length) |
at countItems (main.js:2:15) | エラーが発生した場所(countItems の2行目、15文字目) |
| その下の行たち | 呼び出し元の履歴(processData → main) |
4. デバッグ手順(初心者向けの3ステップ)
ステップ1:最初の行(エラーの種類と原因)を読む
例:
TypeError: Cannot read properties of undefined (reading 'length')
👉 「どんな種類のエラーか」「何をしようとして失敗したか」を把握。
この時点で「undefined に .length を使った」ことがわかる。
ステップ2:最初の at ... 行を見る
at countItems (main.js:2:15)
👉 「エラーが実際に起きた場所」。
その関数・行番号を開いて原因を探す。
ステップ3:下に並ぶ at ... 行を追う
呼び出し履歴(スタック)をたどることで、
「どの関数から呼ばれた結果こうなったのか」を把握。
つまり:
main() → processData() → countItems()
という流れで countItems の中で問題が起きたことが分かる。
5. Error オブジェクトの中身を自分で見る
try…catch の中で、キャッチした例外オブジェクト e の中には name, message, stack が入っています。
try {
throw new Error("何かがおかしい!");
} catch (e) {
console.log("エラー名:", e.name);
console.log("メッセージ:", e.message);
console.log("スタック:", e.stack);
}
JavaScript出力例:
エラー名: Error
メッセージ: 何かがおかしい!
スタック: Error: 何かがおかしい!
at <anonymous>:2:9
at ...
6. デバッグ時のコツ(実践ポイント)
| 状況 | ヒント |
|---|---|
| stack に複数の関数が出てくる | 一番上が「エラーが起きた場所」。下に行くほど「呼び出し元」。 |
| ファイル名:行:列 | main.js:15:3 → エディタでその位置に飛ぶ(VSCodeならクリックでOK)。 |
| スタックが長い | ライブラリやフレームワーク内部の関数は無視して、自分のコードの部分だけ見る。 |
| スタックが表示されない | エラーをキャッチしたあとに console.error(e) ではなく console.error(e.stack) を出すと見える。 |
7. 例題:stack情報を使ってログを整形
function riskyTask() {
throw new Error("処理に失敗しました");
}
try {
riskyTask();
} catch (e) {
console.error("=== エラー発生 ===");
console.error("メッセージ:", e.message);
console.error("発生箇所:\n" + e.stack);
}
JavaScript出力例:
=== エラー発生 ===
メッセージ: 処理に失敗しました
発生箇所:
Error: 処理に失敗しました
at riskyTask (main.js:2:9)
at <anonymous>:6:3
こうすると、ログファイルに残しても**「どこで何が起きたか」**がすぐ分かります。
8. さらに一歩:デバッグツールの活用
| ツール | 説明 |
|---|---|
| 🧭 ブラウザの DevTools(Chrome / Firefox) | 「Sources」タブでブレークポイントを置いて、エラー発生時に変数の中身を確認できる。 |
🧱 Node.js の --inspect オプション | VSCode などで Node.js コードをステップ実行できる。 |
| 🪶 console.trace() | 例外が起きなくても、呼び出し履歴を表示できる。 |
例:
function step1() {
console.trace("ここまでの呼び出し経路");
}
function step2() {
step1();
}
step2();
JavaScript出力例:
Trace: ここまでの呼び出し経路
at step1 (main.js:2:11)
at step2 (main.js:5:3)
at <anonymous>:7:1
まとめ:stack を見れると一気に上達!
| 覚えるポイント | 意味 |
|---|---|
e.name | エラーの種類(TypeError, ReferenceError など) |
e.message | 何が問題だったかの説明 |
e.stack | どの関数・ファイル・行番号で起きたかの履歴 |
try/catch | エラーをキャッチして安全に処理できる |
console.trace() | 任意の地点で呼び出し経路を調べられる |
