「動かない…なんで?」を自分で解決するための基本とツールの使い方
JavaScriptを書いていると、ほぼ100%の確率で「思ったとおりに動かない…」という瞬間がきます。
それはあなただけじゃなくて、現場のエンジニア全員そうです。
むしろ「どう壊れているかを調べて直す力(=デバッグ力)」こそが実務でめちゃくちゃ重要になってきます。
この章では次のことをまとめて学びます。
- どんな種類のエラーがあるのか
 - エラーをどんな流れで探していけばいいのか
 - ブラウザの開発者ツール(デベロッパーツール)をどう使えばいいのか
 - 実際にコードを止めて、値をのぞき見する方法(ブレークポイント / debugger)
 
「バグを直すのが怖い → バグが来ても落ち着いて原因を切り分けられる」に変えていきましょう。
目次
デバッグって何をすること?
デバッグとは、ざっくりいうと
- おかしな挙動(バグ・エラー)を見つけて
 - なんでそうなってるか原因を突き止めて
 - 直す
 
という一連の作業のことです。
「デバッグできるようになる=詰まったときに自力で前に進めるようになる」なので、これは本当に強いです。
エラーには大きく2種類ある
JavaScriptでは、エラーといっても全部同じではありません。よく出てくるのは次の2タイプです。
1. 文法エラー(構文エラー)
- 書き方そのものが間違っていて、そもそも実行できない状態。
 - たとえばカッコが閉じていないとか、
constのつもりがcnotsとタイプミスしたとか。 - ブラウザのコンソールに 
SyntaxError: ...のようなエラーメッセージが出ます。 - どこで壊れてるかをブラウザが教えてくれるので、比較的直しやすいです。
 
イメージ:
function hello( {
  console.log("Hi!");
}
// ↑ カッコが合ってないので構文エラー
2. ロジックエラー(実行時の間違い)
- コード自体は動く。でも「期待した結果になってない」パターン。
 - たとえば計算がずれている、想定外の値が入っている、if の分岐が間違ってる、など。
 - 実行はできるのでブラウザは「壊れてますよ」とは教えてくれないこともあります。
 - これがいちばん時間がかかるし、心を削ってくるところです。
 
イメージ:
function add(a, b) {
  return a - b; // 本当は足し算したいのに引き算してる
}
console.log(add(5, 3)); // 期待は8なのに2になる
この「ロジックエラー」をつぶすときに本気で役に立つのが、ブラウザに内蔵されている デベロッパーツール(開発者ツール) なんです。
デベロッパーツールとは?
Chrome や Edge などのブラウザには、開発者向けのツールセットが最初から入っています。
これが「デベロッパーツール(開発者ツール / DevTools)」と呼ばれるものです。
開き方の例(Chrome / Edge 共通):
- Windows: 
F12キー、または右クリック →「検証」 - Mac: 
⌥Option + ⌘Command + I(もしくは右クリック →「検証」) 
このツールでできることの一部:
- コンソール(Console)で値を出力・確認する
 - 実際に動いているJavaScriptを途中で止めて、中身をのぞく
 - 1行ずつ実行して「どこでおかしくなったか」を追跡する
 - その瞬間の変数の中身を見る
 
つまり「なんで壊れてるか」を調べるためのレントゲンです。
デバッグの第一歩:console.log()とalert()
エラーの原因を調べたいとき、まず多くの人がやるのが「値を出して確認する」です。
console.log(…)
const price = 1200;
console.log("priceの中身:", price);
こうすると、デベロッパーツールの Console(コンソール)タブ に値が表示されます。
「このタイミングでこの値が入ってるんだな」を見るのに便利。
alert(…)
alert("ここまで処理きたよ!");
これは画面上にポップアップを出す方法です。
DevToolsを開いていなくても確認できるので、超シンプルな確認には便利。
ただし何回も出るとストレスなので乱用はしない感じです。
でも…
ログをガンガン仕込んでいくやり方は、数行ならいいんですが、処理が長くなると逆に追いにくくなりますよね。
もっとスマートに「途中で止めて中身を見る」ことができたら最高です。
それが次の「debugger」と「ブレークポイント」です。
コードを途中で止める:debugger; を入れる
debugger; という1行を書くと、その行でプログラムの実行がピタッと止まります。(デベロッパーツールを開いた状態で有効)
止まった時点で、変数の中身や処理の流れをじっくり観察することができます。
サンプルHTML(入力フォーム+JS)
<!DOCTYPE html>
<html>
  <head>
    <title>フォーム入力のハイライト</title>
    <link rel="stylesheet" href="./style.css">
  </head>
  <body>
    <div id="panel">
      <form>
        <div class="form-field">
          <label for="user_name">ユーザー名:</label>
          <input type="text" id="user_name">
        </div>
        <div class="form-field">
          <label for="password">パスワード:</label>
          <input type="password" id="password">
        </div>
        <div class="form-field">
          <label for="pref">都道府県:</label>
          <select id="pref">
            <option value="1">北海道</option>
            <option value="2">青森県</option>
            <option value="3">岩手県</option>
            <option value="4">秋田県</option>
            <option value="5">宮城県</option>
            <option value="6">福島県</option>
          </select>
        </div>
        <div class="form-field">
          <label for="comment">その他(自由記入)</label>
          <textarea id="comment" rows="5" cols="50"></textarea>
        </div>
      </form>
    </div>
    <script src="./focus_debug_sample.js"></script>
  </body>
</html>
サンプルJS(debugger; で止める)
// フォーカスが当たったときの処理
function handleFocus(evt) {
  debugger; // ←ここで実行が一時停止する
  // いったん全部のclassをリセット
  for (const el of fields) {
    el.removeAttribute("class");
  }
  // 今フォーカスが当たった要素だけclassを付ける
  evt.target.setAttribute("class", "is-active");
}
// 入力系の要素をまとめて取得(input, select, textarea)
const fields = document.querySelectorAll("input, select, textarea");
// 全部に「フォーカスされたら handleFocus を呼ぶ」よう登録
for (const item of fields) {
  item.addEventListener("focus", handleFocus);
}
実際にやる手順はこうなります
- ブラウザでこのページを開く
 - デベロッパーツール(開発者ツール)を開く
 - フォームのどこかをクリックしてフォーカスする
 debugger;の行で実行が止まる
止まっている間は、DevToolsのConsoleタブで fields や evt.target などの変数名を入力すると、その瞬間の中身を確認できます。
つまり、
- どの要素が拾えてる?
 - ちゃんとclass外れてる?
 - どの要素に 
is-active付こうとしてる?
をリアルタイムで覗ける、ってことです。 
ブレークポイントでコードを止める(手動でストップ位置を指定する)
debugger; を書き込まなくても、ブラウザ側で「この行で止めて」と指定することもできます。
これがブレークポイントです。
ブレークポイントを使うと、
- 好きな行で実行を一時停止できる
 - 止めた時点での変数の値をチェックできる
 - そこから1行ずつ動かせる(ステップ実行)
 - 関数の呼び出し経路(どこから呼ばれたか)まで見れる
 
という、かなり本格的なデバッグができます。
ブレークポイントの練習用サンプル
これは簡単な「四則演算フォーム」です。演算子(+、-、×、÷)と2つの数字を入力すると結果を表示します。
HTML
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>四則演算デバッグ練習</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <form>
      <h2>四則演算テスター</h2>
      <input type="number" id="val1" />
      <select id="op">
        <option value="add">+</option>
        <option value="sub">-</option>
        <option value="mul">×</option>
        <option value="div">÷</option>
      </select>
      <input type="number" id="val2" />
      =
      <span id="answer"></span>
    </form>
    <script src="./calc_debug_sample.js"></script>
  </body>
</html>
CSS(見やすさ用)
* {
  font-size: 24px;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
  background: #eeeeee;
  margin: 0;
  overflow: hidden;
}
form {
  margin-top: 20px;
  zoom: 2;
  text-align: center;
}
input[type="number"] {
  width: 30px;
}
#answer {
  width: 30px;
  display: inline-block;
}
JavaScript
// 入力が変わったら計算しなおす関数
function refreshResult() {
  // 計算結果を作る
  const out = doMath(
    Number(firstNum.value),   // 1つ目の数字
    Number(secondNum.value),  // 2つ目の数字
    operatorSelect.value      // 選択中の演算子
  );
  // 計算結果を画面に表示
  outputArea.innerHTML = out;
}
// 計算の中身
function doMath(a, b, kind) {
  let result;
  switch (kind) {
    case "add":
      result = plus(a, b);
      break;
    case "sub":
      result = minus(a, b);
      break;
    case "mul":
      result = times(a, b);
      break;
    case "div":
      result = divide(a, b);
      break;
  }
  return result;
}
// 足し算
function plus(a, b) {
  return a + b;
}
// 引き算
function minus(a, b) {
  return a - b;
}
// 掛け算
function times(a, b) {
  return a * b;
}
// 割り算
function divide(a, b) {
  return a / b;
}
// それぞれの要素を取得
const operatorSelect = document.getElementById("op");
const firstNum       = document.getElementById("val1");
const secondNum      = document.getElementById("val2");
const outputArea     = document.getElementById("answer");
// 入力や選択が変わったときに計算し直すようイベント登録
operatorSelect.addEventListener("change", refreshResult);
firstNum.addEventListener("change", refreshResult);
secondNum.addEventListener("change", refreshResult);
ブレークポイントの置き方(Chrome / Edge)
- デベロッパーツールを開く
 - 上部のタブから Sources をクリック
 - 左側にあるファイル一覧(Pageなどと表示されているツリー)から 
calc_debug_sample.jsを選ぶ - 右側にソースコードが表示されるので、止めたい行番号をクリックする
 
すると、その行に青いマーク(または矢印・●の印)がつきます。
これがブレークポイントです。
たとえば switch (kind) { ... } の行あたりにブレークポイントを置いておくと、どの演算が選ばれたのか、a と b に何が入っているのかをその瞬間でチェックできます。
止まっているときに何ができるの?
ブレークポイントで実行が止まった状態になると、デベロッパーツールの右側パネルなどでこんなことができます。
1. 変数の中身を確認する
- ソースコード上でマウスカーソルを変数名に乗せると、その時点の値がポップアップで表示されます。
 - Consoleタブで変数名を直接入力しても、その値が見られます。
 
「いま firstNum.value はちゃんと数字になってる?」
「kind は ‘add’ のはずだけど違う値入ってない?」
といった確認が一発でできます。
2. Scope(スコープ)を見る
DevToolsには「Scope」みたいな領域があり、今実行中の関数内で使える変数(ローカル変数など)が一覧で見られます。
複雑なオブジェクトの中身も展開して追えるので、フォームの値や処理途中の一時変数を丁寧に見たいときに便利です。
3. Call Stack(コールスタック)を見る
「この関数ってどこから呼ばれたんだっけ?」という呼び出し履歴も見られます。
とくにプロジェクトが大きくなると、「誰がこの関数叩いてるの?」が分からなくなるので、ここはかなり役立ちます。
一時停止した後の操作(ステップ実行)
止まったあとの画面には、再生ボタンや矢印アイコンが並びます。
これらで“どんな進め方をするか”をコントロールできます。
よく使うものだけ押さえておきましょう:
- ▶(再開 / Resume)
- 今止まってるところからプログラムを再開します。
 - 次のブレークポイントがあれば、そこでまた止まります。
 
 - ⤵ Step Over(ステップオーバー)
- 今の行を実行して、次の行でまた止まります。
 - その行が関数呼び出しだったとしても、中身の中には入らず、ひとまとめで「呼んだことにして」進んでくれるイメージです。
 - 「ざっくり流れを追いたいとき」に便利。
 
 - ⤴ Step Into(ステップイン)
- 関数呼び出しの行だった場合、その関数の中に潜って、1行ずつ見に行きます。
 - 「この関数の中でバグってそうなんだよな…」というときに使います。
 - かなり細かく追いかけたいとき向け。
 
 - ↩ Step Out(ステップアウト)
- 今入っている関数の残りを一気に実行し、呼び出し元に戻ります。
 - 深いところに潜りすぎたからとりあえず抜けたい、というときに便利。
 
 
この「1行ずつ確かめる」っていう感覚は、はじめて触ると地味に感動します。
何がいつ実行されるのか、頭の中じゃなくて実際の流れで理解できるようになるからです。
まとめ(ここを押さえておくと安心)
- バグは必ず出ます。むしろ「バグの探し方」を知ってる人が強いです。
 - エラーには「文法エラー(すぐ気づける系)」と「ロジックエラー(動くけどおかしい系)」がある。
 console.log()やalert()は、どこまで動いてるか・何が入っているかを手早く確認するための基本の道具。- もっと丁寧に調べたいときは、開発者ツールを開いて、
debugger;で好きな場所で停止させる- ブレークポイントで任意の行に停止ポイントを置く
 - 変数の中身をリアルタイムで見る
 - ステップ実行で1行ずつ動きを追いかける
 
 - これができるようになると「なんか動かないから一旦やり直そう…」ではなく、「どこからおかしいのか順番に見よう」に変わります。これは本当に大きな差になります。
 
いま「正直ちょっとむずかしそうかも」と感じたとしても大丈夫です。
このあとのフェーズ(フォーム処理・API通信・DOM操作・イベント処理など)に進むと、デバッグは必ず必要になります。
そこで少しずつ触っていけば手になじんでいきます。
焦らなくて大丈夫です。

	

