このチュートリアルでは、DevTools で JavaScript の問題をデバッグするための基本的なワークフローを説明します。この記事を読み進めるか、このチュートリアルのビデオ版をご覧ください。
バグを再現する
デバッグの最初のステップは、バグを一貫して再度発生させる一連のアクションを特定することです。
- 新しいタブで こちらのデモを開きます。
- [Number 1] ボックスに「
5
」と入力します。 - [番号 2] ボックスに「
1
」と入力します。 - [Add Number 1 and Number 2] をクリックします。ボタンの下のラベルに
5 + 1 = 51
と表示されます。結果は6
になります。このバグを、これから修正します。
この例では、5 + 1 の結果が 51 になっています。6 にする必要があります。
Sources パネルの UI に精通する
DevTools には、CSS の変更、ページ読み込みパフォーマンスのプロファイリング、ネットワーク リクエストのモニタリングなどのさまざまなタスクのためのさまざまなツールが用意されています。[ソース] パネルで JavaScript をデバッグします。
DevTools を開くと、[ソース] パネルが表示されます。
[ソース] パネルには次の 3 つのセクションがあります。
- ファイルツリーが表示された [ページ] タブ。ページによってリクエストされているすべてのファイルがここにリストされます。
- [コードエディタ] セクション。[ページ] タブでファイルを選択すると、そのファイルの内容がここに表示されます。
[デバッガ] セクション。ページの JavaScript を検査するための各種ツール。
DevTools ウィンドウの幅が広い場合、デフォルトでは [デバッガ] が [コードエディタ] の右側に表示されます。この場合、[Scope] タブと [Watch] タブは、[Breakpoints]、[Call stack] などのセクションと並んで、折りたたみ可能なセクションとして表示されます。
ブレークポイントでコードを一時停止する
このような問題をデバッグする一般的な方法は、コードに console.log()
ステートメントを多数挿入して、スクリプト実行時のそれぞれの値を検査するというものです。次に例を示します。
function updateLabel() {
var addend1 = getNumber1();
console.log('addend1:', addend1);
var addend2 = getNumber2();
console.log('addend2:', addend2);
var sum = addend1 + addend2;
console.log('sum:', sum);
label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
}
console.log()
メソッドでも目的を達成することはできますが、ブレークポイントを使用したほうがより速く処理することができます。ブレークポイントを使用すると、コードの実行中にコードを一時停止し、その時点におけるすべての値を調べることができます。ブレークポイントには、console.log()
メソッドに比べて次のような利点があります。
console.log()
を使用した場合、ソースコードを手動で開き、関係するコードを探し、console.log()
ステートメントを挿入し、ページを再読み込みして、Console でメッセージを確認する必要があります。ブレークポイントを使用した場合は、コードの構造を知らなくても、関係するコードで一時停止することができます。console.log()
ステートメントには、検査する値を 1 つずつ明示的に指定する必要があります。ブレークポイントを使用すると、その時点のすべての変数の値が DevTools に表示されます。コードに影響する変数が他にもあったことに気付かされる場合もあります。
このように、ブレークポイントを使用するなら、console.log()
を使用する方法よりも速くバグを見つけて修正することができます。
先ほどのデモに戻って、このアプリがどのように動作するかを考えると、経験に基づいて、間違いの合計(5 + 1 = 51
)は [Add Number 1 and Number 2] ボタンに関連付けられた click
イベント リスナーで計算されると推測することができます。そのため、click
リスナーが実行されるタイミング前後のコードを一時停止することになります。イベント リスナー ブレークポイントを使用すると、次のとおりに操作できます。
- [デバッガ] セクションで [イベント リスナー ブレークポイント] をクリックしてセクションを開きます。DevTools に、Animation や Clipboard などの展開可能なイベント カテゴリのリストが表示されます。
- [マウス] イベント カテゴリの横にある [展開] をクリックします。DevTools に、click や mousedown などのマウスイベントのリストが表示されます。各イベントの横にはチェックボックスがあります。
[クリック] チェックボックスをオンにします。これで、DevTools はいずれかの
click
イベント リスナーが実行されると自動的に一時停止するようセットアップされます。デモに戻り、[Add Number 1 and Number 2] をもう一度クリックします。DevTools はデモを一時停止し、[Sources] パネルでコード行をハイライト表示します。DevTools はコードの次の行で一時停止しているはずです。
function onClick() {
コードの別の行で一時停止している場合は、正しい行で一時停止するまで [
Resume Script Execution] を押します。
イベント リスナー ブレークポイントは、DevTools で利用可能な数多くの種類のブレークポイントの 1 つに過ぎません。いろいろあるタイプをすべて調べておくだけの価値はあります。それぞれのタイプがいろいろな状況で迅速にデバッグするのに非常に役立つからです。各タイプをいつどのように使用したらよいかについては、ブレークポイントでコードを一時停止するを参照してください。
コードのステップ実行
バグの一般的な原因の 1 つは、スクリプトの実行順序が間違っていることです。コードをステップ実行すると、コードを 1 行ずつ実行して、予想とは異なる順序で実行されているコード行を見つけることができます。今すぐ試す:
DevTools の [Sources] パネルで、[
Step into next function call] をクリックし、onClick()
関数の実行を 1 行ずつステップ実行します。DevTools では次のコード行がハイライト表示されます。if (inputsAreEmpty()) {
[
Step over next function call] をクリックします。DevTools は、ステップ実行せずに
inputsAreEmpty()
を実行します。DevTools が数行のコードをスキップしていることに注意してください。これは、inputsAreEmpty()
が false と評価されたため、if
文のコードブロックが実行されなかったからです。
以上がコードをステップ実行する際の基本的な考え方です。get-started.js
のコードを確認すると、updateLabel()
関数のどこかにバグがあることがわかります。コードの各行をステップ実行する代わりに、別のタイプのブレークポイントを使用すると、バグがあると思われる箇所の付近でコードを一時停止することができます。
コード行のブレークポイントを設定する
コード行のブレークポイントは、最も一般的なタイプのブレークポイントです。特定のコード行で一時停止したい場合は、コード行のブレークポイントを使用します。
updateLabel()
の最後のコード行を確認します。label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
コードの左側には、この特定のコードの行番号 32 が表示されています。[32] をクリックします。DevTools により、32 の上に青いアイコンが配置されます。このアイコンは、この行にコード行のブレークポイントがあることを示します。これで、DevTools は、このコード行が実行される前に常に一時停止します。
[
] [Resume script execution] をクリックします。スクリプトは、行 32 に到達するまで実行されます。行 29、30、31 で、DevTools はaddend1
、addend2
、sum
の値を宣言の横にインラインで表示します。
この例では、DevTools は行 32 のコード行のブレークポイントで一時停止します。
変数の値を確認する
addend1
、addend2
、sum
の値に問題がありそうです。これらは引用符で囲まれており、文字列として扱われているようです。これがバグの原因であると考えられます。ここでさらに情報を収集しましょう。DevTools には変数値を調べるためのたくさんのツールがあります。
方法 1: スコープを検査する
コードのある行で一時停止すると、[スコープ] タブに、実行のこの時点で定義されているローカル変数とグローバル変数が、それぞれの値とともに表示されます。クロージャ変数が存在すれば、それも表示されます。コード内の行で一時停止していない場合、[スコープ] タブは空になります。
変数値をダブルクリックすると、値を編集できます。
方法 2: Watch 式
[Watch] タブでは、変数の値を時間の経過に伴ってモニタリングできます。Watch は変数に限定されません。有効な JavaScript 式は [Watch] タブに保存できます。
今すぐ試す:
- [視聴] タブをクリックします。
- [ ] [Watch 式を追加] をクリックします。
- タイプ
typeof sum
。 - Enter キーを押します。DevTools に
typeof sum: "string"
が表示されます。コロンの右側の値が式の結果です。
このスクリーンショットは、typeof sum
Watch Expression を作成した後の [Watch] タブ(右下)を示しています。
予想どおり、sum
は、数字である必要がありますが、文字列として評価されています。これがバグの原因であることが、ここではっきりしました。
方法 3: コンソール
console.log()
メッセージを表示するだけでなく、任意の JavaScript ステートメントを評価するためにも Console を使用できます。デバッグのために、Console を使用して、バグの潜在的な修正をテストすることができます。今すぐ試す:
- [Console] ドロワーを開いていない場合は、Escape キーを押して開きます。ドロワーは DevTools ウィンドウの下部に開きます。
- コンソールに
parseInt(addend1) + parseInt(addend2)
と入力します。addend1
とaddend2
がスコープ内であるコード行で一時停止しているので、このステートメントは実行されます。 - Enter キーを押します。DevTools は文を評価し、
6
を出力します。これは、デモで生成されるべき結果です。
このスクリーンショットは、parseInt(addend1) + parseInt(addend2)
を評価した後の [Console] ドロワーを示しています。
修正を適用する
バグの修正対象箇所が見つかりました。あとはコードを編集してデモを再度実行し、正しく修正されたか確認するだけです。修正を適用するために DevTools を閉じる必要はありません。JavaScript コードは DevTools UI 内で直接編集できます。今すぐ試す:
- [ ] [Resume script execution] をクリックします。
- コードエディタで、行 31 の
var sum = addend1 + addend2
をvar sum = parseInt(addend1) + parseInt(addend2)
に置き換えます。 - Command+S キー(Mac)または Control+S キー(Windows、Linux)を押して変更を保存します。
- [ Deactivate breakpoints] をクリックします。アクティブであることを示す青色に変わります。この設定の間、DevTools は設定したすべてのブレークポイントを無視します。
- さまざまな値でデモを試してみましょう。デモは正しく計算するようになりました。
次のステップ
このチュートリアルでは、ブレークポイントの設定方法を 2 つだけ説明しましたが、DevTools では、他にも次のような多くの方法を利用できます。
- 指定した条件が満たされた場合にのみトリガーされる条件付きブレークポイント。
- 捕捉された例外または捕捉されていない例外に対するブレークポイント。
- リクエストした URL が指定した文字列に部分一致した場合にトリガーされる XHR ブレークポイント。
各タイプをいつどのように使用したらよいかについては、ブレークポイントでコードを一時停止するを参照してください。
このチュートリアルでは説明していませんが、コードをステップ実行するためのコントロールが他にもいくつかあります。詳細については、行コードをステップ オーバーするをご覧ください。