JavaScript をデバッグする

Sofia Emelianova
Sofia Emelianova

このチュートリアルでは、DevTools で JavaScript の問題をデバッグするための基本的なワークフローを説明します。以下を読み進めるか、このチュートリアルの動画版をご覧ください。

バグを再現する

バグを常に再現できる一連の操作を見つけることが、デバッグを行う際の最初のステップです。

  1. 新しいタブでこちらのデモを開きます。
  2. [番号 1] ボックスに「5」と入力します。
  3. [番号 2] ボックスに「1」と入力します。
  4. [Add Number 1 and Number 2] をクリックします。ボタンの下のラベルには 5 + 1 = 51 と表示されます。結果は 6 になります。これは修正するバグです。

5 + 1 の計算結果は 51 です。6 にする必要があります。

この例では、5 + 1 の計算結果は 51 です。6 にする必要があります。

[ソース] パネルの UI について

DevTools には、CSS の変更、ページ読み込みパフォーマンスのプロファイリング、ネットワーク リクエストのモニタリングなど、さまざまなタスク向けのさまざまなツールが用意されています。[ソース] パネルでは、JavaScript をデバッグします。

  1. DevTools を開くと、[ソース] パネルが表示されます。

    [ソース] パネル。

[ソース] パネルには次の 3 つのセクションがあります。

[ソース] パネルの 3 つのセクション。

  1. ファイルツリーが表示された [ページ] タブ。ページがリクエストするすべてのファイルがここに表示されます。
  2. [コードエディタ] セクション。[ページ] タブでファイルを選択すると、そのファイルの内容がここに表示されます。
  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() メソッドでも目的を達成できますが、breakpointsを使用すると、より迅速に目的を達成できます。ブレークポイントを使用すると、コードの実行中にコードを一時停止し、その時点でのすべての値を調べることができます。ブレークポイントには、console.log() メソッドに比べて次のようなメリットがあります。

  • console.log() を使用する場合、コンソールにメッセージを表示するには、ソースコードを手動で開き、関連するコードを見つけて console.log() ステートメントを挿入し、ページを再読み込みする必要があります。ブレークポイントを使用すると、コードの構造を知らなくても、関連するコードを一時停止できます。
  • console.log() ステートメントでは、検査する各値を明示的に指定する必要があります。ブレークポイントを使用すると、その時点でのすべての変数の値が DevTools に表示されます。コードに影響を与えている変数に気付いていないこともあります。

つまり、ブレークポイントを使用すると、console.log() メソッドよりも迅速にバグを見つけて修正できます。

アプリの仕組みをよく考えてみると、間違った合計(5 + 1 = 51)が、[Add Number 1 and Number 2] ボタンに関連付けられている click イベント リスナーで計算されていると推測できます。そのため、click リスナーの実行時にコードを一時停止することをおすすめします。イベント リスナー ブレークポイントを使用すると、次のことを行えます。

  1. [デバッガ] セクションで [イベント リスナー ブレークポイント] をクリックしてセクションを開きます。DevTools に、アニメーションクリップボードなど、展開可能なイベントカテゴリのリストが表示されます。
  2. [マウス] イベント カテゴリの横にある [展開] をクリックします。DevTools には、clickmousedown などのマウスイベントのリストが表示されます。各イベントの横にチェックボックスがあります。
  3. [クリック] チェックボックスをオンにします。これで、任意の click イベント リスナーが実行されると、DevTools が自動的に一時停止するように設定されます。

    [クリック] チェックボックスがオンになっている。

  4. デモに戻り、[Add Number 1 and Number 2] をもう一度クリックします。DevTools はデモを一時停止し、[ソース] パネルでコード行をハイライト表示します。DevTools は、次のコード行で一時停止する必要があります。

    function onClick() {
    

    別のコード行で一時停止している場合は、正しい行で一時停止するまで [ Resume Script Execution] を押します。

イベント リスナー ブレークポイントは、DevTools で利用できる多くの種類のブレークポイントの 1 つにすぎません。各タイプは最終的にさまざまなシナリオをできるだけ早くデバッグするのに役立つため、すべてのタイプを検討することをおすすめします。各タイプの使用方法とタイミングについては、ブレークポイントを使用してコードを一時停止するをご覧ください。

コードをステップ実行する

バグの一般的な原因の 1 つは、スクリプトが間違った順序で実行されることです。コードをステップ実行すると、コードの実行を 1 行ずつ確認し、想定とは異なる順序で実行されている場所を正確に特定できます。今すぐ試す:

  1. DevTools の [ソース] パネルで、 [次の関数呼び出しにステップイン] をクリックして、onClick() 関数の実行を 1 行ずつステップ実行します。DevTools で次のコード行がハイライト表示されます。

    if (inputsAreEmpty()) {
    
  2. [ Step over next function call] をクリックします。

    DevTools は、inputsAreEmpty() にステップインせずに inputsAreEmpty() を実行します。DevTools が数行のコードをスキップしていることに注目してください。これは、inputsAreEmpty() が false と評価されたため、if ステートメントのコードブロックが実行されなかったためです。

これがコードのステップ実行の基本的な考え方です。get-started.js のコードを確認すると、バグは updateLabel() 関数のどこかにあることがわかります。コードのすべての行をステップ実行するのではなく、別のタイプのブレークポイントを使用して、バグの可能性のある場所の近くでコードを一時停止できます。

コード行のブレークポイントを設定する

コード行ブレークポイントは、最も一般的なタイプのブレークポイントです。一時停止する特定のコード行がある場合は、コード行ブレークポイントを使用します。

  1. updateLabel() のコード最後の行を見てみましょう。

    label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
    
  2. コードの左側には、この特定のコード行の行番号(32)が表示されます。[32] をクリックします。DevTools では、32 の上に青いアイコンが表示されます。これは、この行にコード行ブレークポイントがあることを意味します。このコード行が実行される前に、DevTools が常に一時停止するようになりました。

  3. [ Resume script execution] をクリックします。スクリプトは、32 行目に到達するまで実行を続けます。29 行目、30 行目、31 行目では、DevTools によって addend1addend2sum の値が宣言の横にインラインで表示されます

DevTools は、32 行目のコード行ブレークポイントで一時停止します。

この例では、DevTools は 32 行目のコード行ブレークポイントで停止します。

変数の値を確認する

addend1addend2sum の値が不審なようです。引用符で囲まれているため、文字列です。これは、バグの原因を説明するための良い仮説です。次に、詳細情報を収集します。DevTools には、変数値を調べるための多くのツールが用意されています。

方法 1: スコープを検査する

コードの行で一時停止すると、[スコープ] タブに、実行のこの時点で定義されているローカル変数とグローバル変数、および各変数の値が表示されます。適用可能な場合は、クロージャー変数も表示されます。コードの行で一時停止していない場合、[スコープ] タブは空白になります。

変数値をダブルクリックして編集します。

[スコープ] ペイン。

方法 2: Watch 式

[Watch] タブでは、変数の値の経時的な変化をモニタリングできます。Watch は変数に限りません。有効な JavaScript 式は [Watch] タブに保存できます。

今すぐ試す:

  1. [視聴] タブをクリックします。
  2. [] [Watch 式を追加] をクリックします。
  3. タイプ typeof sum
  4. Enter キーを押すと、DevTools に typeof sum: "string" と表示されます。コロン右側の値は式の結果です。

[Watch 式] ペイン

このスクリーンショットは、typeof sum ウォッチ式式を作成した後の [ウォッチ] タブ(右下)を示しています。

予想どおり、sum は数値であるべきところ文字列として評価されています。これがバグの原因であることを確認できました。

方法 3: コンソール

console.log() メッセージを表示するだけでなく、コンソールを使用して任意の JavaScript ステートメントを評価することもできます。デバッグに関しては、コンソールを使用してバグの修正候補をテストできます。今すぐ試す:

  1. コンソール ドロワーが開いていない場合は、Esc キーを押して開きます。DevTools ウィンドウの下部に開きます。
  2. コンソールで parseInt(addend1) + parseInt(addend2) と入力します。このステートメントは、addend1addend2 がスコープ内にあるコード行で一時停止しているため機能します。
  3. Enter キーを押すと、DevTools はステートメントを評価し、6 を出力します。これは、デモで生成される結果です。

スコープ内の変数を評価した後のコンソール ドロワー。

このスクリーンショットは、parseInt(addend1) + parseInt(addend2) を評価した後の [コンソール] ドロワーを示しています。

修正を適用する

バグの修正方法を見つけた。残す作業は、コードを編集してデモを再実行し、修正を試すことだけです。修正を適用するために DevTools を終了する必要はありません。JavaScript コードは DevTools UI 内で直接編集できます。今すぐ試す:

  1. [ Resume script execution] をクリックします。
  2. コードエディタで、31 行目の var sum = addend1 + addend2var sum = parseInt(addend1) + parseInt(addend2) に置き換えます。
  3. 変更を保存するには、Command+S キー(Mac)または Ctrl+S キー(Windows、Linux)を押します。
  4. [ ブレークポイントを無効にする] をクリックします。有効になると色が青に変わります。この設定が有効になっている間、DevTools は設定したブレークポイントを無視します。
  5. さまざまな値でデモを試してみてください。デモが正しく計算されるようになりました。

次のステップ

このチュートリアルでは、ブレークポイントを設定する 2 つの方法のみを説明しました。DevTools には、次のような多くの方法があります。

  • 指定した条件が true の場合にのみトリガーされる条件付きブレークポイント。
  • キャッチされた例外またはキャッチされなかった例外のブレークポイント。
  • リクエストされた URL が指定した部分文字列と一致したときにトリガーされる XHR ブレークポイント。

各タイプの使用方法とタイミングについては、ブレークポイントを使用してコードを一時停止するをご覧ください。

このチュートリアルでは説明していないコードステップ コントロールがいくつかあります。詳細については、コード行をステップオーバーするをご覧ください。