イベントの発火を操る3つのインスタンスメソッド

## イベント
イベントとはマウスクリックやドラッグ&ドロップなどユーザーの操作によって発生する動作や、Local Storageの操作のようなシステムで生じた出来事のことを指します。
JavaScriptを用いることでイベントが発火した時に特定のJavaScriptの関数を実行させられます。その関数のことをイベントハンドラと呼び、それをイベントに紐づけるように定義することをイベントハンドラを登録すると言います(イベントハンドラはJavaScriptの関数と書きましたが、厳密にはそれに限定せず実行される特定のコードブロックのことを指します)。
下の例では`button`という`id`を持つ要素をクリックしたときにアラートを出すようなイベントハンドラを登録しています。
```js
const button = document.getElementById('button');
button.addEventListener('click', () => {
  alert('clicked')
});
```
`addEventListener`でイベントハンドラの登録を行なっています。第1引数で登録するイベントを指定して、第2引数でイベントハンドラを記述します。
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="MWZqVmB" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/MWZqVmB">
  EventHandler</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

イベントハンドラではさらに、[`Event`インターフェイス](https://dom.spec.whatwg.org/#interface-event)を介してイベントのプロパティやメソッドを呼び出せます。
`target`プロパティでイベントの発火元、`type`プロパティでイベントの種類のように様々な情報を扱えます。例えば以下の例では`Event`から`timeStamp`を取得してそれを表示させています。
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="zYyJjbZ" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/zYyJjbZ">
  EventHandler</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

次に下記のようなHTML構造を考えます。
```
- div
    - div
        - button
```
そして、すべての要素のクリックに対してイベントハンドラが登録されているとします。その時、`button`をクリックすると`button`のイベントハンドラが発火し、その親の`div`に登録されたイベントハンドラ、さらにその親の`div`に登録されたイベントハンドラが発火します。

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="WNLgZgo" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/WNLgZgo">
  Event</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

この現象はバブリングと呼ばれる仕組みによって生じます。
バブリングはイベントが生じた時に、その要素のイベントハンドラを実行し、次にその親要素のイベントハンドラを実行し、さらにその親のイベントハンドラを実行するようにイベントハンドラを対象の要素から親要素へと辿って実行することを指します。
先ほどの例では`div→div→button`という構造でしたので、`button`のイベントハンドラが発火、内側の`div`のイベントハンドラが発火、外側の`div`のイベントハンドラが発火の順で処理されました。

## stopPropagation
例えばリンクによるページ遷移を行う場合にその親のクリックイベントを発火させないようにバブリングを止めたいことがあります。その時は、対象のイベントハンドラで`Event`を受け取って`stopPropagation`を呼び出すことでバブリングを阻止できます。
```js
const button = document.getElementById('button');
button.addEventListener('click', (e) => {
  e.stopPropagation();
  alert('clicked')
});
```
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="XWoxGMB" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/XWoxGMB">
  stopPropagation</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## stopImmediatePropagation
`Event`が持つ似たようなメソッドとして`stopImmediatePropagation`があります。
`stopImmediatePropagation`もバブリングに関するメソッドで、`stopPropagation`は親要素のイベントハンドラの実行を防ぐだけだったのに対して、このメソッドはそれ以降に登録された同要素に対してのイベントハンドラの発火も防ぎます。
```js
const button = document.getElementById('button');
// 発火する
button.addEventListener("click", () => {
  alert(1);
});
// 発火する
button.addEventListener("click", (e) => {
  e.stopImmediatePropagation();
  alert(2);
});
// 発火しない
button.addEventListener("click", () => {
  alert(3);
});
```
以下の例では`button`に対してそれぞれ２つのイベントハンドラを登録し、1つ目のイベントハンドラでそれぞれ`stopPropagation`、`stopImmediatePropagation`を呼び出すことで動作差分を確認できます。
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="KKbGEvX" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/KKbGEvX">
  stopImmidiatePropagation</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## preventDefault
ブラウザにはそれぞれのイベントに対するデフォルトの挙動が実装されています。例えばチェックボックスにはクリックすると見た目が切り替わる挙動が実装されています。
チェックボックスのクリックに対して`e.preventDefault`を呼び出すイベントハンドラを登録するとその挙動が呼び出されません。
```js
const input = document.getElementById("remove");
input.addEventListener('click', (e) => {
  e.preventDefault();
});
```

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="MWZqGXw" data-user="kokisakano" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kokisakano/pen/MWZqGXw">
  EventHandler</a> by KokiSakano (<a href="https://codepen.io/kokisakano">@kokisakano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>