このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

【JavaScript入門】デフォルトの処理の停止

デフォルトの処理の停止

 DOM イベントは「発生元 → 親要素 → … → window」へと泡のように伝わる バブリング と、リンク遷移やフォーム送信など要素固有の デフォルト動作 を伴います。
JavaScript ではイベントオブジェクトの

  • preventDefault() … デフォルト動作を無効化
  • stopPropagation() … 伝播(バブリング/キャプチャ)を停止
    を使い、挙動を細かくコントロールできます。

 ここでは両メソッドの違いと併用パターンを整理し、クリック時にフォーム送信を止めつつ特定階層だけでハンドリングを完結させるデモを作成します。

1.イベント伝播を理解する

1.1. バブリングの流れ

バブリングとは

 1 つの要素で発生したイベントが “内側 → 外側” へと親要素を順番にさかのぼりながら再び発火していく仕組みです。
水中の泡(bubble)が上にのぼる様子にたとえて Event Bubbling と呼ばれます。

window
└─ document
   └─ html
      └─ body
         └─ #outer
            └─ #inner   ← ここをクリック
  1. #innerclick が発生
  2. 同じ click イベントが #outer でも発火
  3. 続いて bodyhtmldocumentwindow と伝播
  4. 最終的に親のない window で終了

 ブラウザは 最も深いターゲット要素でリスナーを実行してから 親ノードへ移動し、リスナーがあれば順次呼び出します。

途中で stopPropagation() を呼ぶとそれ以上上位へ届かない。

1.2. キャプチャ位相(参考)

 addEventListener(type, fn, {capture:true}) を指定すると “親→子” 順で処理されるキャプチャ位相でハンドラを実行できる。

2.デフォルト動作とその無効化

2.1 .preventDefault()

 リンク遷移・フォーム送信・チェックボックスの ON/OFF など ブラウザが自動で行う動作 をキャンセルする。

2.2. returnValue との関係

preventDefault() 実行後は event.returnValue === false になる(読み取り専用)。

3.バブリング停止とデフォルト抑止の API

メソッド効果伝播デフォルト
stopPropagation()上位へイベントを渡さない✋ 停止✅ 継続
preventDefault()標準アクションを無効➡️ 継続❌ 無効
両方呼ぶ伝播も動作も止める✋ 停止❌ 無効

4.サンプルプログラム ― 送信を止めて伝播もカット

ファイル名: stop_default_demo.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>デフォルトの処理の停止デモ</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
section{border:1px solid #999;padding:1rem;margin:1rem 0}
button{padding:.4rem 1rem}
</style>
</head>
<body>

<section id="panel">
  <form id="orderForm" action="https://example.com/order" method="post">
    <input name="item" value="カプチーノ">
    <button id="saveBtn">注文を送信</button>
  </form>
</section>

<script>
/* ---------- 最下層: ボタンクリック ---------- */
const btn = document.getElementById('saveBtn');
btn.addEventListener('click', e => {
  console.log('#saveBtn クリック');
  e.stopPropagation();     // ①バブリングをここで止める
});

/* ---------- 中間層: フォーム送信 ---------- */
const form = document.getElementById('orderForm');
form.addEventListener('submit', e => {
  console.log('#orderForm submit');
  e.preventDefault();      // ②ページ遷移(送信)を無効化
});

/* ---------- 上位層: section クリック ---------- */
document.getElementById('panel').addEventListener('click', () => {
  console.log('#panel click (ここは呼ばれない)');
});

/* ---------- 最上位: window クリック ---------- */
window.addEventListener('click', () => {
  console.log('window click (ここも呼ばれない)');
});
</script>
</body>
</html>

デバックコンソールの出力

#saveBtn クリック
#orderForm submit
  • #panelwindow のハンドラは 発火しないstopPropagation() が有効。
  • フォームは送信されずページ遷移もしない → preventDefault() が有効。

ブラウザの出力例

プログラム解説

なぜ「中間層: フォーム送信」で preventDefault() を使うのか

 「stopPropagation();」で バブリングしているのになぜ、「中間層: フォーム送信」で「preventDefault();」しているのか。

/* ---------- 最下層: ボタンクリック ---------- */
const btn = document.getElementById('saveBtn');
btn.addEventListener('click', e => {
  console.log('#saveBtn クリック');
  e.stopPropagation();     // ①バブリングをここで止める
});

/* ---------- 中間層: フォーム送信 ---------- */
const form = document.getElementById('orderForm');
form.addEventListener('submit', e => {
  console.log('#orderForm submit');
  e.preventDefault();      // ②ページ遷移(送信)を無効化
});

topPropagation() の役割

  • イベントの伝播の停止
    btn のクリックイベントで e.stopPropagation(); を呼び出すことで、このクリックイベントが親要素へバブリング(伝播)するのを防いでいます。
    つまり、ボタンで発生したクリックイベントが、フォームやその他の上位要素に伝わらなくなります。

preventDefault() の役割

  • ブラウザの既定動作のキャンセル
    一方、フォームの submit イベントで e.preventDefault(); を呼び出しているのは、フォーム送信というブラウザのデフォルト動作(例えば、ページ遷移やサーバへの送信リクエスト)をキャンセルするためです。
    これにより、送信ボタンをクリックした際、フォームの通常の送信動作が行われず、JavaScriptでフォーム送信後の処理(例:Ajax送信やカスタムな検証処理)を行えるようになります。

両者は別々の役割を持つ

  • stopPropagation()
    はイベントの伝播を制御し、特定の階層以降でイベントが処理されることを防ぎます。
  • preventDefault()
    はイベントに対してブラウザが既定で行う動作を抑止します。

フォームの送信動作を止める必要がある

 ボタンクリックで stopPropagation() を呼んでいるからといって、フォームの送信自体はブラウザの標準動作として行われる可能性があります。
 たとえば、ボタンがフォーム内に配置され、ボタンの種類が submit である場合、クリック後にフォームの送信処理が実行されます。
 このとき、フォーム送信イベントが発生しますが、これをそのままにすると、ページがリロードされたり、サーバにデータが送信されたりしてしまいます。
 そのため、「中間層」でフォームの submit イベントに対して preventDefault() を適用し、こうしたデフォルト動作をキャンセルしています。

ポイント
16action に外部 URL を指定し通常なら遷移するフォーム
26ボタンクリックで 伝播だけ を停止
32submit ハンドラで デフォルト送信 を無効化
38–44上位階層にリスナーを置き、停止効果を確認

まとめ

  • バブリング停止stopPropagation()(UI を局所化したいとき)。
  • デフォルト動作無効preventDefault()(独自 Ajax 送信や SPA ナビゲーションなど)。
  • 両方を組み合わせることで「イベントはここで完結させ、標準処理も行わせない」という細かな制御が可能。イベント制御は UI フレームワークでも頻出するため、基礎をしっかり押さえておきましょう。