JavaScript 第5回 addEventListenerのコールバック関数設定で間違えたので

# はじめに
第3回、4回の記事では、addEventListenerメソッドを使用して、ボタン押下時の動作を試してきました。
addEventListenerの構文の一つのaddEventListener(type, listener)において、listener部分は、「イベント発生時に通知を受け取るオブジェクトで、関数。」でしたが、この関数は、コールバック関数と呼ばれます。
今回は、このコールバック関数について、理解したいと思います。
addEventListenerのlistener設定で誤った設定をしてしまい、はまったので記録しておきたいと思います。

# 今回実施する内容
コールバック関数を使用して、Hello world!を画面に表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/23067031-ec61-8c20-e1fd-34ab9063cc81.png)

# ソースコード(Git Hub)
https://github.com/Build-Mount/JS_05_callback
- callback.html
- callback.js

# 環境
OS: Windows 11 JP (64bit)
Microsoft Edge: バージョン 119.0.2151.58 (公式ビルド) (64 ビット)

# 参考
[EventTarget: addEventListener() メソッド](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener)
[Callback function (コールバック関数)](https://developer.mozilla.org/ja/docs/Glossary/Callback_function)

# 用語

# コールバック関数とは？
[Callback function (コールバック関数)](https://developer.mozilla.org/ja/docs/Glossary/Callback_function)によると、
> コールバック関数とは、引数として他の関数に渡され、外側の関数の中で呼び出されて、何らかのルーチンやアクションを完了させる関数のことです。
とあります。

要するに、**関数の引数に関数を持てる**と理解しました。したがって
- **この引数に持つ関数をコールバック関数と呼ぶ。**
- **コールバック関数の実行タイミングは、元の関数の指定の箇所**
- **呼び出すコールバック関数は、呼び出し元関数実行時に指定できる**
ということですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/4af20091-486e-1410-c403-da5e8728ff2e.png)

イメージ的には、以下のようですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/a6ffd113-45b5-5645-dc38-e92aafbff766.png)

**元の関数の中で、一部の処理を別の関数に任せたいというときに、コールバック関数を使用する**ということだと思います。
これが、addEventListenerのlistenerの引数部分であり、ボタン押下のイベントは共通ですが、押下したときの動作は、スクリプト作成者自身が決められるということだと思いました。

# コールバックの記載例
## ソースコード
シンプルなコールバックの例を記載します。
```html:callback.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>onclick event</title>
	<script src="callback.js" defer></script>
</head>
<body>
    結果
    <p id="output"></p>
</body>
</html>
```
```JavaScript:callback.js
function hello() {
  return `Hello world!`;
}

function callbackMoto(callbackSaki) {
  document.getElementById("output").textContent = callbackSaki();
}

callbackMoto(hello);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/160fc47c-9a01-0565-83e5-ab9b51a8606a.png)

## コールバックソースの説明
HTMLファイルについては、第1回から記載しており、特に説明することはありません。
### `callback.js`について
- function helloがコールバック関数です。単に`hELLO WORLD!`を返すだけの関数です。
- function callbackMotoがコールバックを実装する関数で、引数に`callbackSaki`を持ち、ここにcallback関数を設定します。
- `document.getElementById("output").textContent = callbackSaki();`のところで、`callbackSaki();`とすることで、ここでcallbackSakiで指定した関数を実行します。
- `callbackMoto(hello);`は、callbackMoto関数を実行しており、引数を`hello`とし、コールバック関数を呼び出しています。これを実行すると、「Hello world!」が画面に表示されます。

# 「JavaScript 第3回 addEventListenerでボタン押下動作」での過ち
[JavaScript 第4回 onClickとaddEventListenerを両方設定したら？](https://qiita.com/Mount/items/5c1b965b09ed8ea11310)では、onClick属性とaddEventListenerメソッドを使用して、ボタン押下時に画面に文字列を表示するスクリプトを作成しました。
このときのJavaScriptのソースコードは、以下の通りでした。
```JavaScript:onclickAddEventListener.js
document.getElementById("btn").addEventListener("click", btnClick);
document.getElementById("btn").addEventListener("click", btnClick2);

function btnClick() {
    document.getElementById("output").textContent = "addEventListener";
    document.getElementById("output3").textContent = "addEventListener";
};

function btnClick2() {
    document.getElementById("output4").textContent = "addEventListener2つ目";
};

function btnOnClick() {
    document.getElementById("output").textContent = "onclick";
    document.getElementById("output2").textContent = "onclick";
};
```
でやらかしたのは、こんな感じです。
```JavaScript:やらかしたonclickAddEventListener.js
document.getElementById("btn").addEventListener("click", btnClick());
document.getElementById("btn").addEventListener("click", btnClick2());

function btnClick() {
    document.getElementById("output").textContent = "addEventListener";
    document.getElementById("output3").textContent = "addEventListener";
};

function btnClick2() {
    document.getElementById("output4").textContent = "addEventListener2つ目";
};

function btnOnClick() {
    document.getElementById("output").textContent = "onclick";
    document.getElementById("output2").textContent = "onclick";
};
```

何を間違えたかというと先頭行の記載で、`btnClick`とすべきところを`btnClick()`としてしまったのです。
```JavaScript:やらかしたonclickAddEventListener.jsの抜粋
document.getElementById("btn").addEventListener("click", btnClick());    //btnClick()と()をつけた
document.getElementById("btn").addEventListener("click", btnClick2());   //btnClick2()とをつけた
```

こうすると、ボタン押下しなくてもbtnClick関数が動作してしまい、ボタンの意味がなくなってしまいました。
listenerはオブジェクトか関数を記載するのですが、()を付与するとその時点で関数を実行してその結果のオブジェクトを返してしまうということだろうと思います。

# おわりに
addEventListener関数などで、実行する関数を記載して実装をしており、コールバック関数って何？と疑問持つことなく使っていましたが、今回コールバック関数を勉強させていただきました。

今回の例はとてもシンプルなため、コールバック関数をどのように使いこなすのか？イメージつきにくいような気もしますが、今のところ自分でコールバック関数を呼ぶような関数を作る予定はありません。
当面は、もっぱら、addEventlistenerのような引数にコールバック関数をもつメソッドを使う側かなと思いました。

今回の例はコールバック関数を、別に定義するような実装にしましたが、インターネットで見られるのは、無名関数、アロー関数式を使用したものが大半ですから、それにも慣れていったほうがよさそうだなと思いました。