第1回

無料公開中公開翌日4時まで

ブレークポイントの基本

ChromeのDevToolsを例に、ブレークポイントの使い方を解説します。プログラムの任意の行を基準に、処理が進む過程をコントロールしながら、関数の実行や、変数の内容などを検証していくことができます。

(616号)

目次
シェア

デバッグスキルを高める

プログラマに必要とされるスキルはいくつかありますが、その中でもエラーの原因をすばやく突き止めることができる、デバッグのスキルは非常に重要なスキルのひとつです。

デバッグのスキルは経験に依存するところも大きいですが、ツールの使い方を知り、使いこなせることも重要です。

本シリーズでは、ChromeのDevToolsを利用したJavaScriptのデバッグ手法を解説します。

最初に取り上げるのは、ブレークポイントという機能です。この機能を使って途中でプログラムの実行を止めることで、効率的にデバッグする手法を紹介します。

console.logでのデバッグ

JavaScriptを普段書いている人であれば、console.logを使ったことがないという人はまずいないでしょう。

console.logを使うと、プログラム実行中の変数の状態を出力できたり、特定の行が実行されているかを確認できたりと、開発時には大変便利な機能です。

console.logで要素を取得する例
const $el = document.querySelector('.foo');

console.log($el); // 要素が取得できているか確認

console.logだけでもある程度のケースはカバーできますが、今回紹介するブレークポイントを使うと、console.logだけではデバッグが難しいケースでも、効率よくデバッグすることができるようになります。

ブレークポイントの設定

ブレークポイントは、プログラムの実行を任意の場所で一時停止する機能です。停止した場所の変数の状態やコールスタック(関数の呼び出し経路)を確認したり、停止した場所からコードの実行を一つ一つ自分で進めることができます。

次の例を元にブレークポイントの使い方を解説していきます。

解説に利用するコード
function sum(arr) {
  const _sum = arr.reduce((a, b) => {
    return a + b
  })

  return _sum
}

function average(arr) {
  const _sum = sum(arr)
  const _avg = _sum / arr.length

  return _avg
}

const avg = average([1, 2, 3, 4, 5])
console.log(avg)

配列で渡した数値の合計を返すsum関数*と、平均値を返すaverage関数があり、average関数は内部でsum関数を利用しています。

ここで、average関数を実行したときの動作をブレークポイントを使って追いかけてみます。

次のサンプルで、[新規タブで開く]をクリックして、別タブで表示してください。

ブレークポイントの解説に使うサンプル

そして、DevToolsの[ソース]タブを開き、左上の[ナビゲータを表示]ボタンをクリックすると、左側にファイルの一覧が表示されます。

[ソース]タブ左上に[ナビゲータを表示]ボタンがある
スクリーンショット:「ソース」タブの左上に「ナビゲータを表示」ボタンがあり、クリックするとナビゲータパネルが表示される。画面右側にはブレークポイントやコールスタックなどの項目がリスト形式で並んでいる。中央には、フォルダを同期する方法についての説明が表示されている。大きな画像

表示されたファイルの一覧の中から、デバッグしたいソース(app.js)を選択することで、ソースコードを見ながらデバッグすることができます。

app.jsを開き、ソースコードを表示させた
スクリーンショット:左側にディレクトリツリーが、右側にディレクトリツリーで選択したファイル内のソースコードが表示されている。ここでは、top/codegrid.github.io>2025-js-debug>breakpoint>breakpoint/>app.jsが選択されている。大きな画像

このように、[ソース]タブでブレークポイントを設定したいファイルを開いたら、左側の行番号が書いてある部分をクリックすることで、ブレークポイントを設定することができます。

まずはaverageの最初の行(10行目)をクリックします。

ブレークポイントを設定したい箇所をクリックすると行に青いマークがつく
スクリーンショット:「ソース」タブでブレークポイントを設定したい10行目をクリックすると、青いマークが行番号の横に表示される。右側のパネルには「ブレークポイント」セクションがあり、設定したブレークポイントの情報が表示されている。この例では、「app.js」ファイルの10行目にブレークポイントが設定されている。大きな画像

すると、左側に青い矢印のようなマークがつきます。これがブレークポイントを設定した状態です。

この状態でリロードすると10行目で処理が止まり、次のような状態になります。

設定した箇所で処理が止まった状態
スクリーンショット:設定したブレークポイントで処理が一時停止した状態を示している。「ソース」タブでは10行目に黄色いハイライトが表示され、現在の処理位置がわかる。また、右側の「ブレークポイント」セクションでは、停止した場所と関連する情報が表示されている。「ブレークポイントで一時停止しました」というメッセージが画面上部に表示され、変数の値(この場合、arr = [1, 2, 3, 4, 5])がデバッグ情報として確認できる。大きな画像

この状態では、JavaScriptの処理が黄色い背景の行の前で完全にストップした状態になります。たとえば、ブラウザのスクロールなども動きませんし、ページの読込中であれば、このスクリプト以降のHTMLのレンダリングも行われず、ブラウザのページのタブには、読込中のクルクルが出たままの状態になります。

処理を進める

ブレークポイントを設定した行の直前で処理が止まった状態から、手動で処理を進めることで、デバッグを行っていきます。

処理を進めるには、右上にあるいくつか矢印のボタンを使います。

処理を進めるためのボタン
スクリーンショット:「ソース」タブでは現在の処理位置が10行目に停止しており、右上にデバッグ操作用のボタンが6つ並んでいる。ボタンの内容については、以降の本文を参照。大きな画像
処理を進めるためのボタン(拡大した図)
スクリーンショット:6つのデバッグ操作用のボタンを拡大したところ。大きな画像

これらは左から順に、次のような役割を持つボタンです。

  • 処理の再開/停止
  • ステップオーバー
  • ステップイン
  • ステップアウト
  • ステップ
  • ブレークポイントの有効/無効の切り替え

特に重要なのは、ステップオーバー、ステップイン、ステップアウトの3つのボタンです。それぞれについてどのような動作なのかを解説します。

ステップオーバー

ステップオーバーは、現在の行を実行し、次の行に処理を進める基本的な操作です。もし現在の行に関数呼び出しがあったとしても、呼び出された関数内部へはジャンプせずに関数を実行し、次の行に進みます。

ただし、次の行に進むだけで、その行が実行されるわけではありません。

ステップオーバーを行うボタン
スクリーンショット:左から2つ目にあるステップオーバーを行うボタンがハイライトされている状態を示している。「ソース」タブでデバッグが10行目に一時停止している。大きな画像

前述の例では、average関数の最初の行(10行目)にブレークポイントを設定していました。この状態でステップオーバーを行うと、次のようになります。

ステップオーバーを1回押した状態
スクリーンショット:ステップオーバーを1回実行した結果、処理が10行目から11行目に進んだ状態を示している。「ソース」タブでは、現在の処理位置が黄色いハイライトで11行目に表示されている。9行目にはarr = (5) [1, 2, 3, 4, 5]という表示が、10行目には_sum = 15という赤くインライン表示が追加されている。大きな画像

sum関数が実行されていますが、sum関数内部にはジャンプせず、次の行に進んでいることがわかります。

ここで、9行目にはarr = (5) [1, 2, 3, 4, 5]という表示が、10行目には_sum = 15というインライン表示が追加されています。

薄い赤色の背景付きのこれらの表示は、関数に渡された引数の値や、変数の現在の値を示すものです。

このように、処理を進めていくごとに値のインライン表示が追加されていくため、意図しない値の変化が起きていないかどうか、1行ずつ確かめながらデバッグすることができます。

ステップイン

ステップインも、現在の行を実行し、次の行に進める操作です。ステップオーバーとは異なり、呼び出された関数内部の処理も一つ一つ追いかけることができます。

ステップインでは、もし現在の行に関数呼び出しがあった場合、その関数の定義箇所にジャンプし、関数の内部に処理を進めます。

ステップインを行うボタン
スクリーンショット:ステップインを行うボタンがハイライトされている状態を示している。「ソース」タブで現在の処理が10行目に停止している。大きな画像

average関数の最初の行(10行目)でステップインを行うと次のようになります。

ステップインを1回押した状態
スクリーンショット:ステップインを1回実行した結果、処理が関数の内部に進んだ状態を示している。この例では、処理位置が2行目で、黄色のハイライトで示されている。変数arrの値は[1, 2, 3, 4, 5]であることが赤くインライン表示されている。大きな画像

今度はsum関数の内部にジャンプしたことがわかります。

この状態で再度ステップインを行うと、さらにreduceメソッドの引数として指定した関数の内部にジャンプします。

ステップインをもう一度押した状態
スクリーンショット:ステップインをもう一度押した結果、現在の処理位置が3行目のreturn a + bに移動し、黄色のハイライトで示されている。変数aとbの値が、a = 1, b = 2と赤くインライン表示されている。大きな画像

reduceメソッドによって繰り返し呼び出される関数は、aとbという2つの引数を持ちますが、これらの現在の値a = 1, b = 2が2行目にインライン表示されていることに注目してください。

続けてステップインを実行していくことで、引数の値の変化をインライン表示で確認しながらデバッグすることができます。

ステップインを繰り返すと値のインライン表示が変化する
スクリーンショット:黄色のハイライトは3行目のreturn a + bのままだが、変数aとbの値が、a = 3, b = 3と変わり、赤くインライン表示されている。大きな画像

このように、ステップインは関数内部の処理のデバッグに役立ちます。

なお、関数呼び出しがない行では、ステップオーバーとステップインはどちらを押しても同じ結果になります。

ステップアウト

関数内部から脱出し、関数呼び出し後の処理に進むには、ステップアウトを使います。

ステップアウトでは、現在の行の呼び出し元の関数が終了するまで実行し、関数を抜けます。

ステップアウトを行うボタン
スクリーンショット:ステップインを行う、左から4つ目のボタンがハイライトされている状態を示している。「ソース」タブで現在の処理が10行目に停止している。大きな画像

average関数の最初の行(10行目)でステップアウトを行うと次のようになります。

ステップアウトを1回押した状態
スクリーンショット:ステップアウトを1回押した結果、現在の関数の処理を抜け出し、呼び出し元のスコープに戻った状態を示している。この例では、関数averageの処理を抜け出して、17行目のconsole.log(avg)に移動したことがわかる。17行目は黄色くハイライトされている。大きな画像

average関数を呼び出していた16行目の処理が終わった状態になり、17行目にジャンプしたことがわかります。

このように、ステップオーバー、ステップイン、ステップアウトをうまく使うことで、処理を進めていくのが基本的な使い方です。

ソースコード中でブレークポイントを設定する

本記事ではDevToolsからブレークポイントを設定しましたが、この方法のほかに、JavaScriptのソースコードの中でブレークポイントを指定する方法もあります。

ブレークポイントを設定したい行の前にdebugger文を書いておくことで、DevToolsからブレークポイントを設定したときと同じ動作になります。

ソースコードの中にブレークポイントを設定した場合
function average(arr) {
  debugger;
  const _sum = sum(arr);
  const _avg = _sum / arr.length;

  return _avg;
}

ただし、ユーザーが利用する環境にdebugger文が残ってしまうと、ユーザーの利用中に処理が止まってしまうので注意が必要です。

まとめ

今回は、ChromeのDevToolsを使って、JavaScriptのコードにブレークポイントを設定し、そこから処理を進めていく基本的な操作を解説しました。

ChromeのDevtoolsには、ブレークポイントで処理を進めていく中で、合わせて活用すると便利な機能があります。変数の値を変えながら検証したり、関数がどのような順番で呼び出されるかを確認したり、といった機能です。

次回は、これらの機能も合わせて、ブレークポイントを活用していきましょう。

この記事の内容についての意見・感想を送る
CodeGridのDiscordで知識を深めよう。参加する。

人気のシリーズ