【JavaScript】関数と宣言② 〜関数式・アロー関数・コールバック関数〜

# 概要
...『[【JavaScript】関数と宣言① 〜関数の宣言・呼び出し・引数〜](https://qiita.com/andota05/items/a32d5fee352f17ea1361)』の続きです。

JavaScriptを学習、理解を深めるため「[JavaScript Primer 迷わないための入門書](https://jsprimer.net/)」を読み、
理解した内容等を記載していく。

「[【JavaScript】JavaScript入門一覧](https://qiita.com/andota05/items/22fae452225b785fd405)」に他の記事をまとめています。

# この記事で理解できること
* 関数式の定義方法
* Arrow Function(アロー関数)の定義方法
* コールバック関数の定義方法
* メソッドの定義方法

# 関数はオブジェクト
* JavaScriptにおける関数は`関数オブジェクト`とも呼ばれるオブジェクトの一種。
* `( )無し`で関数名のみを呼び出した場合、関数を`オブジェクトとして`参照できる。
* また、関数は数字や文字列など他の値と同様に`変数へ代入したり、関数の引数として渡す`ことが可能。

```js
// 関数を定義
function objFunc() {
    console.log("objFunc関数が呼び出された");
};

// ()を付けて関数を呼び出す
objFunc();              // => objFunc関数が呼び出された

// ()無しで関数名のみを出力
console.log(objFunc);   // => ƒ objFunc() {
                        //    console.log("objFunc関数が呼び出された");
                        //    }
                        // オブジェクトとして表示されていることを確認

// ()無しの関数オブジェクトを変数に代入し、関数を呼び出してみる
const funcObj = objFunc;
funcObj();              // => objFunc関数が呼び出された
```

## 関数式
* 関数を`値として変数へ代入している式`のこと。<br>(関数が値として扱える性質・関数を`ファーストクラスファンクション（第一級関数）`と呼ぶ)
* 関数式の定義方法には`functionキーワード`を使用する方法、`ArrowFunction`(後述)を使用する方法がある。
* `関数宣言は文`、`関数式では関数を値`として扱う。

> **匿名関数(無名関数)**
> 関数式では代入先の変数名で参照できるため、
> 関数宣言時に指定していたような「function 関数名( ) { };」の**関数名部分**を省略できる。
> このような名前を持たない(関数名を省略した)関数を**匿名関数**または**無名関数**と呼ぶ。

```js
// 変数greetingに匿名関数を代入 
const greeting = function() {
  return "おはようございます";
}

console.log(greeting());  // => おはようございます
```

## Arrow Function(アロー関数)
* 矢印のような`=>`(「=」+「>」)を使い、`匿名(無名)関数`を定義する関数式の構文。
* 書き方にいくつかのパターンがあり、省略記法もある。
* `ES2015`から導入されている。

```js
// functionキーワードを使用した場合
const funcA = function() {
   // ...処理内容
};

// Arrow Functionを使用した場合
const funcB = () => {
   // ...処理内容
};
```

### Arrow Function(アロー関数)の省略記法
アロー関数では次の場合、さらに省略した定義方法がある。

* 関数の仮引数が1つの時は`( )`を省略できる。
* 関数の処理が1行で終わるような1つの式の場合、ブロック`{ }`と`return文`を省略できる。(評価結果を返り値とする)

```js
// 定義方法
const funcA = () => { return "funcAを実行"; };                             // 仮引数なしの場合
const funcB = (func) => { return func + "を実行"; };                       // 仮引数1つの場合
const funcC = func => { return func + "を実行"; };                         // 仮引数が1つの場合は、( )を省略できる
const funcD = (func, num) => { return func + "を" + num + "秒後に実行"; };  // 仮引数が複数の場合

// 返り値
const funcE = func => { return func + "を実行"; };  // こう書くこともできるが、funcFのように書くこともできる
const funcF = func => func + "を実行";              // 処理が1行で終わるような1つの式の場合、ブロック{ }とreturnが省略可能

console.log(funcA());            // => funcAを実行
console.log(funcB("funcB"));     // => funcBを実行
console.log(funcC("funcC"));     // => funcCを実行
console.log(funcD("funcD", 3));  // => funcDを3秒後に実行
console.log(funcE("funcE"));     // => funcEを実行
console.log(funcF("funcF"));     // => funcFを実行
```

### Arrow Function(アロー関数)の特徴
* 名前を付けることができない（`常に匿名関数`）
* `this`が静的に決定できる。
* `function`キーワードに比べて短く書くことができる。
* newできない（コンストラクタ関数ではない）
* `arguments`変数を参照できない。

## コールバック関数
* 関数やメソッドに`引数として渡される関数`のこと。
* また、コールバック関数を引数として使う関数やメソッドのことを`高階関数`と呼ぶ。
* 高階関数呼び出し時に引数として直接、`コールバック関数を定義`することも可能。

```js
//　functionキーワードで関数式を定義(コールバック関数として渡す用)
const callBack1 = function () {
    console.log("callBack1です");
};

// Arrow Function(アロー関数)で関数式を定義(コールバック関数として渡す用)
const callBack2 = () => {
    console.log("callBack2です");
};

// コールバック関数用の仮引数を持つ、高階関数「call」を定義
function call(callback) {
    return callback();  // 　処理内容は、引数として受けったコールバック関数を呼び出す
};

// 高階関数「call」に引数としてコールバック関数を渡す
call(callBack1);  // => callBack1です
call(callBack2);  // => callBack2です
```

```js
/*
 * 高階関数内で直接コールバック関数を定義する例
 */

// コールバック関数用の仮引数を持つ、高階関数「call」を定義
function call(callback) {
    return callback();  // ( )付きで関数として呼び出す
};

/*
 * 高階関数「call」を呼び出し、引数としてコールバック関数を直接定義
 */
// funcitonキーワードで作成
call(function () {
    console.log("callBack1です");
});  // => callBack1です

// Arrow Function(アロー関数)で作成
call(() => {
    console.log("callBack2です");
});  // => callBack2です
```

## メソッド
* オブジェクトのプロパティが関数の場合、`メソッド`という呼び方になる。
* `関数`と`メソッド`の機能的な違いはなく、わかりやすさを重視して呼び方が区別されている。
* `オブジェクト.メソッド名()`で呼び出せる。

```js
// プロパティとしてメソッド「method1」「method2」を持つオブジェクトを作成
const obj = {
    // functionキーワードを使用
    method1: function () {
        return "オブジェクトのmethod1です";
    },
    // Arrow Function(アロー関数)を使用
    method2: () => {
        return "オブジェクトのmethod2です";
    }
}

// オブジェクト.メソッド名( )で呼び出す
console.log(obj.method1());  // => オブジェクトのmethod1です
console.log(obj.method2());  // => オブジェクトのmethod2です
```

### メソッドの短縮記法(ES2015〜)
* オブジェクトリテラルの中で`メソッド名(){ メソッドの処理 }`と記載することができる。
* `オブジェクトのメソッド`だけではなく、`クラスのメソッド`と共通の書き方となっている。
* メソッドを定義する場合は、できるだけこの書き方が推奨される(定義方法が統一できるため)

```js
// プロパティとしてメソッド「method1」「method2」を持つオブジェクトを作成
const obj = {
    // 短縮記法：メソッド名(){ メソッドの処理 }
    method1() {
        return "オブジェクトのmethod1です";
    },
    method2() {
        return "オブジェクトのmethod2です";
    }
}

// オブジェクト.メソッド名( )で呼び出す
console.log(obj.method1());  // => オブジェクトのmethod1です
console.log(obj.method2());  // => オブジェクトのmethod2です
```