【JavaScript】高階関数について（コールバック、クロージャ、カリー化）

# はじめに
JavaScriptの高階関数などについて概要をまとめました。
概念的で難しく、かなり理解に苦しみました（まだ全て理解できていないと思います…）。
実際のプログラミングにおいて有効利用するにはもっと習熟しなければいけないと感じました。

# 高階関数
- 関数を返す関数のこと
- 関数をその他のオブジェクトと同様に扱うことで実現されている。このようなことができるプログラミング言語は、**第一級関数**を持つ、という

# コールバック関数
- 他の関数に引数として渡される関数のこと
- 例としては、Array.prototype.map()、Array.prototype.forEach()、setTimeout()など

# クロージャ
- クロージャとは、それが内包する変数や関数などをまとめて閉じ込める役割を果たすものである
- JavaScriptの関数は入れ子にすることができる
- 内側の関数は、外側の関数のスコープ内に存在する変数にアクセスできる
- 一方で、内側の関数には、外側の関数の中からしかアクセスできない
- ゆえに、ある関数の内部は閉じられたひとつの範囲となるから、JavaScriptの関数はクロージャである
- 次の例では、関数`counter`の中がまとめて閉じ込められることとなる。他のいくつかのプログラミング言語の感覚では、変数`count`は関数`counter`が呼び出された後に消滅するように見える。しかし、クロージャである`counter`は、変数`count`と関数`countUp`をまとめて閉じ込めるから、関数`counter`が生存する限り、変数`count`も生存することとなる
- なお、「まとめて閉じ込める」とは、「内部の変数などをメンバとして持つ」という意味**ではない**。次の例において、関数`countUp`が**その内部で変数`count`を参照しているから**、関数`countUp`が存在する限り変数`count`も「合わせてまとめて閉じ込められている」ということである
```js:クロージャの例
function counter () {
  let count = 0;
  function countUp () {
    count += 1;
    return count;
  }
  return countUp;
}

const myCounter = counter();

for (let i = 0; i < 10; i++) {
  console.log(myCounter());
} // 1,2,3,4,5...,10と表示される。
```
- データと関数を結びつけられるという点で、オブジェクト指向的な技術である。メソッドを一つだけ持つオブジェクトのようなものである

# クラス
*20240811　コメントにて教示いただいた内容を元に追記*
- データと関数をひとつにまとめるならば、ES2015以降ではクラスを用いることができる
```js:クラスの例
class MyClass {
    constructor(x) {
        this.x = x;
    }

    incrementX() {
        this.x++;
    }

    get x() {
        return this.x;
    }

    set x(value) {
        this.x = value;
    }
}

const myClassA = new MyClass(1);
```

# カリー化
```js:カリー化の例
function currying(x) {
    return function(y) {
        return x + y;
    };
}

const currying5 = currying(5);
const currying10 = currying(10);

console.log(currying5(2)); //7
console.log(currying10(2)); //12
```
- 上の例の関数`currying`は、カリー化しないのならば下の例のようにも書ける
```js:カリー化しない例
function notCurrying(x, y) {
    return x + y;
}

console.log(notCurrying(5, 2)); //7
console.log(notCurrying(10, 2)); //12
```
- なぜカリー化するかというと、関数を部分的に適用することができるからである。前者の例における次の部分で、いわば新しい関数を作成している
```js:部分適用
const currying5 = currying(5);
const currying10 = currying(10);
```
- クロージャによって、内部の関数が一つ目の引数を保持するため、このようなことができる
- ちなみに、次のようにも呼び出せる
```js:別の呼び方
currying(2)(5);
```
- アロー関数を用いる場合は次のようになる
```js:アロー関数を用いたカリー化の例
const currying = x => y => x + y;
```

# 関数の合成
- 関数型プログラミングでは、小さな関数（純粋関数であるという条件付き）を定義し、それらの関数を合成してプログラミングをする
```js:簡素な関数の合成の例
const compose = (f1, f2) => x => f1(f2(x));
```

# this
- `this`は、呼び出し元によって動的に参照先が変わる。ゆえに、関数の定義だけを見てthisの値が何かを決定できない
- 基本的な参照先はベースオブジェクト（メソッドを呼ぶ際に、そのメソッドのドット演算子またはブラケット演算子のひとつ左にあるオブジェクトのこと）となる
- ただし、アロー関数内で定義された関数やメソッドにおけるthisがどの値を参照するかは関数の定義時に決まる
- アロー関数内のthisの参照は、外側のスコープへと探索していき、見つかったところのthisを示す
- また、`Function.prototype.bind()`によって、引数に指定したオブジェクトを`this`が参照するようにできる
*20240811　コメントにより教示いただいた内容を元に追記*
- クラスにおいて、`this`は、`new`によって生成されたインスタンスを指す
- `constructor`関数における`this`は、インスタンスを示すオブジェクトである

# 参考文献
https://developer.mozilla.org/ja/docs/Glossary/First-class_Function

https://developer.mozilla.org/ja/docs/Glossary/Callback_function

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Functions

https://developer.mozilla.org/ja/docs/Web/JavaScript/Closures

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this

https://jsprimer.net/basic/function-this/

https://jsprimer.net/basic/class/