JavaScriptの基礎 - デバッグ
概要
JavaScriptのデバッグとは、プログラムの動作上の問題を特定して修正するプロセスである。
Web開発においてデバッグは必須のスキルであり、適切なツールと手法を習得することで開発効率が大幅に向上する。
JavaScriptのデバッグには、主に以下の手段が活用される。
| ツール | 説明 |
|---|---|
| consoleオブジェクト | ブラウザのコンソールに変数の値やログを出力するための組み込みオブジェクト |
| ブラウザDevTools | Chrome、Firefox、Edgeなど主要ブラウザに搭載された開発者向け統合ツール |
| ブレークポイント | プログラムの実行を任意の行で一時停止させる機能 |
| debugger文 | JavaScriptコード内に記述するデバッグ用のキーワード |
これらを組み合わせることにより、変数の状態確認、実行フローの追跡、パフォーマンスの計測が可能になる。
特に、Chrome DevToolsのSourcesパネルを活用したブレークポイントデバッグは、複雑なバグの調査において強力な手段となる。
consoleオブジェクト
consoleオブジェクトは、JavaScriptに標準搭載されたデバッグ用の組み込みオブジェクトである。
WebブラウザのコンソールパネルやNode.jsの標準出力にメッセージを送信するための多様なメソッドを提供する。
基本的な出力メソッド
下表に、最もよく使用される出力メソッドを示す。
| メソッド | 説明 |
|---|---|
console.log() |
標準ログを出力する。 デバッグ用途で最も汎用的に使用される。 |
console.info() |
情報レベルのメッセージを出力する。console.log() と同様の動作だが、情報を明示的に区別したい場合に使用する。
|
console.warn() |
警告メッセージを出力する。 コンソール上で黄色のアイコンと共に表示される。 |
console.error() |
エラーメッセージを出力する。 コンソール上で赤色のアイコンと共に表示され、スタックトレースも自動で付加される。 |
使用例を以下に示す。
const user = { name: "Alice", age: 30 };
console.log("ユーザ情報:", user);
console.info("処理開始");
console.warn("非推奨のAPIを使用しています");
console.error("接続に失敗しました");
データ表示メソッド
オブジェクトや配列を視覚的に分かりやすく表示するためのメソッドを以下に示す。
| メソッド | 説明 |
|---|---|
console.table() |
配列やオブジェクトを表形式で表示する。 データの比較や一覧確認に適している。 |
console.dir() |
オブジェクトのプロパティをツリー構造で表示する。 DOM要素やネストされたオブジェクトの内部構造を確認する際に有用である。 |
console.dirxml() |
DOM要素をHTML / XML構造として表示する。 Elementsパネルと同様の階層表示が得られる。 |
使用例を以下に示す。
const users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
];
// 配列を表形式で表示
console.table(users);
// オブジェクトをツリー構造で表示
console.dir(document.body);
タイミング計測
処理時間を計測するためのメソッドを以下に示す。
同一のラベル文字列を使用することで、複数の計測を同時進行させることができる。
| メソッド | 説明 |
|---|---|
console.time('label') |
指定したラベルで計測を開始する。 |
console.timeEnd('label') |
計測を終了し、経過時間をコンソールに出力する。 |
console.timeLog('label') |
計測を継続したまま、その時点の経過時間を出力する。 |
使用例を以下に示す。
console.time("処理時間");
for (let i = 0; i < 1000000; i++) {
// 重い処理のシミュレーション
}
console.timeLog("処理時間"); // 途中経過を出力
for (let i = 0; i < 1000000; i++) {
// 更に処理が続く
}
console.timeEnd("処理時間"); // 計測終了・合計時間を出力
グループ化
関連するログをグループにまとめて表示する機能を以下に示す。
ネストしたグループの作成も可能であり、複雑なデータ構造のデバッグに役立つ。
| メソッド | 説明 |
|---|---|
console.group('label') |
指定したラベルでグループを開始する。 グループは展開された状態で表示される。 |
console.groupCollapsed('label') |
グループを折りたたんだ状態で開始する。 ログが多い場合に視認性を保つために有用である。 |
console.groupEnd() |
現在のグループを終了する。 |
使用例を以下に示す。
console.group("ユーザ処理");
console.log("ユーザを取得中...");
console.group("バリデーション");
console.log("メールアドレスを確認");
console.log("パスワードを確認");
console.groupEnd();
console.log("処理完了");
console.groupEnd();
その他のメソッド
下表に、上記以外の有用なconsoleメソッドを示す。
| メソッド | 用途 |
|---|---|
console.assert() |
条件が偽 (false) の場合のみエラーメッセージを出力する。 |
console.count() |
同じラベルで呼び出された回数をカウントして出力する。 |
console.countReset() |
指定したラベルのカウンタをリセットする。 |
console.clear() |
コンソールの表示内容をクリアする。 |
console.trace() |
その時点のコールスタック (スタックトレース) を出力する。 |
console.debug() |
デバッグレベルのメッセージを出力する。(デフォルトでは非表示の場合あり) |
console.assert() の使用例を以下に示す。
const value = -5;
// 条件が偽の場合のみ出力される
console.assert(value > 0, "valueは正の値である必要があります:", value);
Webブラウザ : DevTools
WebブラウザのDevTools (Developer Tools) は、Chrome、Firefox、Edge等の主要なWebブラウザに搭載された開発者向けの統合デバッグ環境である。
DevToolsを開くには、以下に示すショートカットを使用する。
- [F12]キー
- DevToolsの表示・非表示を切り替える。
- [Ctrl] + [Shift] + [I]キー
- Elementsパネルを表示してDevToolsを開く。
- [Ctrl] + [Shift] + [J]キー
- Consoleパネルを表示してDevToolsを開く。
- [Ctrl] + [Shift] + [C]キー
- Element Inspectorモードを起動する。(ページ上の要素を直接クリックして選択できる)
Elementsパネル
ElementsパネルはページのDOM構造をリアルタイムに表示するパネルである。
HTML要素の階層構造を視覚的に確認でき、CSSスタイルの適用状況も確認・編集が可能である。
下表に、Elementsパネルでできる主な操作を示す。
| 機能 | 説明 |
|---|---|
| DOM構造の確認 | ページを構成する全HTML要素をツリー形式で表示する。 要素を選択すると、対応するスタイル情報が右側のStylesペインに表示される。 |
| スタイルの確認と編集 | Stylesペインで適用されているCSSプロパティを確認し、 値を一時的に変更してレイアウトを調整できる。 |
| 要素の検査 | ページ上の任意の要素を右クリックして[検査]を選択すると、対応するHTML要素にジャンプする。 |
| DOMの編集 | 要素をダブルクリックしてHTMLを直接編集し、ページへの影響をリアルタイムで確認できる。 |
Consoleパネル
Consoleパネルは、JavaScriptの実行ログを確認するための中心的なパネルである。
consoleオブジェクトによる全ての出力 (console.log()、console.error() 等) がここに表示される。
下表に、Consoleパネルでできる主な操作を示す。
| 機能 | 説明 |
|---|---|
| ログの確認 | console.log() 等で出力したメッセージを確認する。エラーや警告はそれぞれ異なる色と記号で表示される。 |
| JavaScriptコマンドの直接実行 | パネル下部の入力欄にJavaScriptを入力してその場で実行できる。 ページの変数やDOM要素に直接アクセスして値を確認・変更することが可能である。 |
| ログのフィルタリング | ログレベル (All / Info / Warnings / Errors) でフィルタリングし、 必要な情報のみを表示できる。 |
Sourcesパネル
SourcesパネルはJavaScriptのソースコードを閲覧し、ブレークポイントを使用したステップ実行を行うためのパネルである。
実行中のコードの状態 (変数の値、コールスタック等) をリアルタイムで確認できる。
下表に、Sourcesパネルでできる主な操作を示す。
| 機能 | 説明 |
|---|---|
| ソースコードの表示 | ページで読み込まれているJavaScriptファイルの一覧と内容を確認できる。 |
| ブレークポイントの設定 | コードの行番号をクリックしてブレークポイントを設定する。 ブレークポイントに達すると実行が一時停止し、その時点の変数の値を確認できる。 |
| ステップ実行 | 実行を1行ずつ進めながら変数の変化を追跡できる。 |
| ソースコードの一時編集 | ファイルを一時的に編集して動作を確認することができる。(ページ再読み込みで元に戻る) |
Networkパネル
Networkパネルは、WebブラウザとサーバとのHTTP通信を全て監視するためのパネルである。
APIリクエストのデバッグや、ページの読み込み速度に影響する通信を特定する時に活用する。
[Ctrl] + [Shift] + [E]キーのショートカット (Chromeの場合) でConsoleパネルから直接移動できる。
下表に、Networkパネルでできる主な操作を示す。
| 機能 | 説明 |
|---|---|
| HTTPリクエスト / レスポンスの監視 | ページが送受信する全てのHTTPリクエストを一覧表示する。 各リクエストのヘッダ、ボディ、レスポンスの内容を詳細に確認できる。 |
| ステータスコードの確認 | 各リクエストのステータスコード (200、404、500等) を一目で確認できる。 |
| 応答時間とデータサイズの確認 | リクエストごとの応答時間とデータサイズを計測し、ボトルネックを特定できる。 |
| リクエストのフィルタリング | XHR、Fetch、JS、CSS等の種別でフィルタリングして、目的のリクエストを素早く見つけられる。 |
下表に、DevToolsの主要パネル一覧を示す。
| パネル名 | 主な用途 | ショートカット |
|---|---|---|
| Elements | DOM構造の確認・CSSの編集 | [Ctrl] + [Shift] + [I]キー |
| Console | ログ確認・JavaScript直接実行 | [Ctrl] + [Shift] + [J]キー |
| Sources | ブレークポイント設定・ステップ実行 | [F12]キー |
| Network | HTTP通信の監視・APIデバッグ | [Ctrl] + [Shift] + [E]キー |
| Performance | ページのパフォーマンス分析 | - |
| Memory | メモリリーク検出・ヒープ分析 | - |
ブレークポイント
ブレークポイントとは、JavaScriptの実行を任意の行で一時停止させるための機能である。
実行が一時停止した時点での変数の値、コールスタック、スコープの内容をリアルタイムで確認できる。
行ブレークポイント
行ブレークポイントは最も基本的なブレークポイントである。
設定方法を以下に示す。
- [F12]キー等を押下して、Chrome DevToolsを開く。
- [Sources]パネルを選択する。
- 対象のJavaScriptファイルを開く。
- 一時停止させたい行の行番号を選択する。
- 行番号が青いマーカーで強調表示されれば、ブレークポイントの設定は完了である。
ページを操作してブレークポイントが設定された行に到達すると、実行が自動的に一時停止する。
条件付きブレークポイント
条件付きブレークポイントを使用すると、指定した条件式が真 (true) の場合のみ実行を一時停止させることができる。
ループ処理の特定のイテレーションや特定の値を持つ場合のみ調査したい場合に有効である。
設定方法を以下に示す。
- [Sources]パネルで対象の行番号を右クリックする。
- [Add conditional breakpoint]を選択する。
- 入力ボックスに条件式を入力する。
- 例: index > 100
- 例: user.name === "Alice"
- [Enter]キーを押下して確定する。
条件式が真と評価された場合のみブレークポイントが機能し、それ以外の場合は実行が継続される。
DOMブレークポイント
DOMブレークポイントは、DOM要素の変化を検知して実行を一時停止させる機能である。
どのJavaScriptコードがDOMを操作しているのかを特定する時に有効である。
設定方法を以下に示す。
- Elementsパネルで対象のDOM要素を選択する。
- 要素を右クリックする。
- [Break on]を選択する。
- 下表の種別から目的に合ったものを選択する。
下表に、選択できる種別を示す。
| 種類 | 説明 |
|---|---|
| Subtree modifications | 対象要素の子孫ノードが追加・変更・削除された場合に停止する。 |
| Attribute modifications | 対象要素の属性 (class、id等) が変更された場合に停止する。 |
| Node removal | 対象要素がDOMから削除された場合に停止する。 |
イベントリスナーブレークポイント
イベントリスナーブレークポイントは、特定のイベントが発生した時に実行を一時停止させる機能である。
クリックやキー入力等、特定のユーザ操作に対応したコードの動作を追跡する場合に有効である。
設定方法を以下に示す。
- [Sources]パネルを開く。
- 右側のサイドバーにある[Event Listener Breakpoints]セクションを展開する。
- 停止させたいイベントのカテゴリ (Mouse、Keyboard、Clipboard等) を展開する。
- 対象のイベント (click、keydown等) にチェックを入力する。
以降、そのイベントが発生するたびに実行が自動的に一時停止する。
ステップ実行
ブレークポイントで実行が一時停止した後は、ステップ実行機能を使用して、処理を1行ずつ進めることができる。
各ステップで変数の値の変化を確認しながら、バグの原因を追跡する。
| コマンド | ショートカット | 説明 |
|---|---|---|
| Resume | [F8]キー | 次のブレークポイントまで実行を再開する。 |
| Step Over | [F10]キー | 次の行に進む。関数呼び出しがあっても関数内には入らない。 |
| Step Into | [F11]キー | 次の行に進む。関数呼び出しがある場合は関数の中に入る。 |
| Step Out | [Shift] + [F11]キー | 現在の関数から抜け出し、呼び出し元の次の行に進む。 |
debugger文
debugger 文は、JavaScriptコード内に直接記述するデバッグ用のキーワードである。
DevToolsが開いている状態でこの文に到達すると、ブレークポイントと同様に実行が自動的に一時停止する。
基本構文
debugger 文の基本的な記述方法を以下に示す。
debugger;
この1行を任意の箇所に挿入するだけで、DevToolsが起動中であればその行で実行が停止する。
DevToolsが閉じている場合は、debugger 文は無視され、処理はそのまま実行される。
使用例
- ループ内の条件に応じて停止させる例
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
if (items[i].price > 100) {
debugger; // 高額商品の処理時に停止
}
total += items[i].price;
}
return total;
}
- エラーステータスの場合のみ停止させる例
function processData(data) { if (data.status === "error") { debugger; // エラーステータスの場合のみ停止 } // 以降の処理... }
注意事項
debugger 文を使用する場合は、以下に示す事柄に注意する必要がある。
- DevToolsが閉じている場合は効果がない。
- DevToolsを開いていない状態では、
debugger文は完全に無視される。 - 本番環境のユーザには影響を与えない。(ただし削除することを強く推奨する)
- DevToolsを開いていない状態では、
- 本番コードには残さない。
- デプロイ前には必ず
debugger文を全て削除すること。 - ESLintの
no-debuggerルールを有効化することにより、削除漏れを自動検出できる。
- デプロイ前には必ず
- ローカル開発環境のみで使用する。
- パフォーマンスに影響する可能性があるため、ローカル開発時のみ使用する。
- CIパイプラインやテスト環境へのコードに含めないよう注意する。
デバッグの実践パターン
一般的なデバッグ手順
不具合を効率的に解決するための手順を以下に示す。
- 問題を再現する。
- バグが発生する具体的な操作手順を特定する。
- 同じ条件で必ず再現するかどうかを確認する。
- 再現条件が複雑な場合は、最小限の再現コードに絞り込む。
- 原因を特定する。
console.log()で怪しい変数の値を確認する。- ブレークポイントを設定して実行フローを追跡する。
- エラーメッセージのスタックトレースから問題箇所を特定する。
- 修正を実装する。
- 根本原因を特定した上で最小限の修正を行う。
- 修正箇所が他の機能に影響しないかを確認する。
- 修正を検証する。
- 同一の再現条件で問題が解決されたことを確認する。
- 関連する機能のテストも実行して副作用がないことを確認する。
よくあるエラーと対処法
Uncaught TypeError: Cannot read properties of undefined
- 原因
- 未初期化または存在しないオブジェクトのプロパティにアクセスしようとしている。
- 対処方法
console.log()で対象変数の値を確認する。- オプショナルチェーン (
?.) を使用してアクセス前にnullチェックを行う。
Uncaught ReferenceError: xxx is not defined
- 原因
- 未宣言の変数を参照している、あるいは、スコープ外の変数にアクセスしている。
- 対処方法
- 変数の宣言位置とスコープを確認する。
- ESLintを導入して事前に検出する。
Uncaught SyntaxError
- 原因
- シンタックスエラー
- 括弧やセミコロンの不一致や予約語の誤用等
- 対処方法
- エラーメッセージに示された行番号を確認する。
- ESLintで事前に検出する。
CORS error
- 原因
- クロスオリジンリクエストがサーバ側のCORSポリシーによって拒否されている。
- 対処方法
- サーバ側で適切な
Access-Control-Allow-Originヘッダを設定する。
- サーバ側で適切な
Failed to fetch
- 原因
- ネットワーク通信エラー
- APIサーバへの接続に失敗している。
- 対処方法
- Networkパネルでリクエストの詳細を確認する。
- サーバの起動状態とURLが正しいかを確認する。
関連情報