React学習を楽にしてくれるJavaScriptでの関数型プログラミングの基礎知識

こんにちは、フロントエンドエンジニアの[てりー](https://twitter.com/teriteri_code)です。
僕の詳しいプロフィールは[こちら](https://terrblog.com/about/)


Reactを仕事で使いこなしたい人、Reactの知識に不安がある人に向けて、具体的な勉強方法のロードマップをまとめました。

https://terrblog.com/react-typescript-how-to-master/

# この記事について
この記事は、「JavaScriptでの関数型プログラミング」について、Reactを学ぶ際に足を引っ張らない程度にまとめました。
普段JavaScriptに触れていながら、Reactへの学習障壁を感じている方などの参考になれば幸いです。

## なぜReact学習において、関数型プログラミングの知識が必要なのか？
ReactのライバルにあたるVue.jsはhtml、cssとVue.js特有のテンプレート構文を組み合わせる事で、JavaScript力が低くても書きやすい作りになっています。

それに対して、Reactは原理がシンプルで一貫しており、特有の決まり事は少ないのが特徴です。
原理の背後ではJavaScriptと関数型プログラミングへの理解を前提としていて、公式ドキュメントなどでも、関数型についての解説はわざわざ行われていません。

サーバーサイドのRubyやPHPではオブジェクト指向が用いられている背景もあって、関数型プログラミングへの理解が求められるReactはVue.jsに比べて学習コストが高いと思われています。

しかし、Reactを学ぶ前に「JavaScriptの基礎」と「関数型プログラミングの理解」さえあれば、React自体はシンプルでとっつきやすい言語だと僕は考えています。

では、React学習を楽にしてくれるJavaScriptでの関数型プログラミングの基礎知識について解説していきます。

# 関数型プログラミンングの5つの特徴

## ①関数でプログラミングを構成する
関数型言語では関数だけでコードを組み立てます。
オブジェクト指向ではクラスを使って、様々な処理を行っていました。

「関数だけで組み立てる！」ときいて、流石に無理だろ！と思った人も多いと思うので、関数型でいう所の関数がどういった意図で使われているのかを説明します。

### 関数型の「関数」とは
よく数学で使う関数と同じ意味でです。
``y = f(x) ``的な感じ。

必ず引数と戻り値があります。
つまり関数型プログラミングとは__「引数→戻り値に変換する関数を組み合わせて構築するプログラミング」__となります。

今後この記事で関数という場合には、関数型プログラミングにおける関数の事を指していきます。

## ②全ての式が値を返す
関数では全てが式として書かれ、値を返します。
### 命令型と宣言型
プログラミングの処理は「命令型」と「宣言型」に分けられます。
命令型は命令文によって順番に状況を変えて行って、最終的に目的の処理を行うやり方です。
手続き型やオブジェクト指向がこれに含まれます。
上から1つずつ処理を追っていけば良いので、直感的に理解しやすいのが特徴です。

宣言型はどんな値が欲しいかを宣言する式を書く事で、目的の値を手に入れます。
SQLなどが代表的で、「欲しいデータに対してSQLを宣言する」といった使い方をします。

宣言型は従来、複雑な処理は難しく、限定的な場面のみで使用されてきました。
関数型プログラミングは宣言型でありながら、複雑な処理が行える点で、オブジェクト指向の次の開発技術として注目された訳です。


言葉だと分かりづらいと思うので簡単な処理で比べてみましょう。
1から100までの数字から6の倍数を格納した配列を吐き出していきます。

### 手続き型
```js
const array = [];
for (let n = 1; n < 101; n += 1) {
  if (n % 6 === 0) {
    array.push(n);
  }
}
console.log(array);
```
手続き型では、命令文によって構成されています。
・array配列を作る
・1から100までの中で6の倍数の物を配列に入れていく
・出力する
といった処理を順番に行っています。

### 関数型
```js
const range = (start, end) =>
  [...new Array(end - start).keys()].map((n) => n + start);
console.log(range(1, 101).filter((n) => n % 6 === 0));
```
関数型は式によって構成されているから、左辺から右辺に評価していく事で値を得ています。
・rangeを作り、引数を入れる事で1~100の配列を作る。
・rangeから6の倍数だけ抜き出す。
といった処理を順番に行っています。

## ③関数を値としても使える
関数型は②で述べた様に必ず値を返しますが、それに加えて関数を値として利用することも可能です。
つまり関数を変数に代入したり、他の関数の戻り値や引数などの設定する事ができます。

このような性質を持った関数を第一級関数と呼びます。
JavaScriptの関数もその性質を持っている為、関数型プログラミングを行う事ができます。

### 高階関数
先ほど述べた「引数に関数を取ったり、戻り値として関数を返したりする関数」のことを高階関数と呼びます。
ちなみにJavaScriptでよく出てくるコールバックは、この際に引数として渡された関数の事です。

例を見ていきましょう。

```js
const data = [2,3,4,5];
const result = data.map(function(value,index,array){
  return value * value;
});
console.log(result);//[4, 9, 16, 25]
```
foreachに近い使われ方をしていますね。
mapは配列の要素を順番に取り出してコールバック関数に渡し,戻り値として加工した結果を返す高階関数です。

今回はdataの中身を順番にコールバック関数に渡し、valueに代入されている為、2→4、3→9と加工されてresultに返ってきています。

Reactでは高階関数の応用として「高階コンポーネント」という、コンポーネントを引数にとってコンポーネントを戻り値として返す概念が使われています。

## ④関数から新しい関数を作る
関数型プログラミングでは、既存の関数と引数を組み合わせる事で、新しい関数を作る事ができます。
主に部分適用という方法で新しい関数を作りますが、その前にカリー化について見ておきましょう。
### カリー化
複数の引数を取る関数を、より少ない引数を取る関数に分割して入れ子にすることをカリー化と呼びます。

```js

//1.カリー化なし
const multiply = (n, m) => n * m;
console.log(multiply(2, 4));// 8


//2.カリー化 
const withMultiple = (n) => { 
  return(m)=>n*m;
};
  
console.log(withMultiple(2)(4));//8 

//3.カリー化(アロー関数使用)
const withMultiple = (n) => (m) => n * m;
console.log(withMultiple(2)(4)); //8 

```
1.で定義した`multiply`はn,mを引数として、その積を返す関数でした。
2.の`withMultiple`はnを引数に取った上で、mを引数に取り、nとmの積を返すという高階関数になります。

要するにカリー化とは
「複数の引数を取る関数を、引数が`元の関数の最初の引数`で、戻り値が`引数として元の関数の残りの引数を取り、それを使って結果を返す関数`である高階関数にする事」 となる訳です。

### 部分適用
さて、カリー化を押さえた上で、部分適用について確認していきましょう。
部分適用とは、カリー化によって関数の一部の引数を固定して新しい関数を作る事です。

コードで見ていきましょう。

```js
const withMultiple = (n) => (m) => n * m; 
console.log(withMultiple(3)(5)); 
//15

const triple = withMultiple(3);
console.log(triple(5));
// 15
```

先ほどのカリー化で作った`withMultiple`に対して、1つ目の引数に3を渡す事で、新しい関数`triple`を作っています。
関数`triple`は1つ目の引数に3が固定されている為、常に3の倍数を返す関数として機能します。

高階関数や部分適用を使うことで、一時的な変数が不要になり、その分コードが簡潔になるという恩恵を受けられます。

## ⑤副作用を起こさない
副作用とは自分以外のコードに影響を及ぼす事を指します。
## 参照透過性
純粋な関数型プログラミングでは、関数は外側の変数を変更しません。引数が同じなら必ず同じ戻り値を吐き出します。これを参照透過性と呼びます。

参照透過性が如何に大事かは、こちらの「プログラマが知るべき97のこと」という名著でも語られています。

[関数型プログラミングを学ぶことの重要性](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/%E9%96%A2%E6%95%B0%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%92%E5%AD%A6%E3%81%B6%E3%81%93%E3%81%A8%E3%81%AE%E9%87%8D%E8%A6%81%E6%80%A7/)

# あとがき
Vue.js→Reactと僕自身が学習を進めていく中で、Vue.jsはweb制作やデザイン側の領域との相性の良さや手軽さを感じ、Reactはプログラミング的な背景と原理への立ち返りを感じました。

フロントエンドはITの中でも特に移り変わりが激しく、新しい技術がどんどん出てくる分野ですが、背景にある原理への理解を深める事が、一番の近道だと改めて感じています。

### 独学でフロントエンドエンジニアを目指している人へ

フロントエンドの仕事を得るまでにどんな勉強をしたら良いのかをまとめました！

興味ある方は是非ご覧ください。

https://terrblog.com/how-to-get-front-end-job/

#### あわせて読みたい

未経験者におすすめの転職エージェント：[未経験のITエンジニア転職におすすめの転職エージェント・転職先](https://terrblog.com/frontend-job-board/)

経験者の場合の副業先：[フルリモート週2~3日からでも副業が出来るエージェント紹介](https://terrblog.com/side-job-agent/)

好条件の正社員転職：[【転職ドラフト指名の画像アリ】2年目で600万の指名を獲得した僕が考える技術自信ナシでも転職ドラフトを使った方が良い理由](https://terrblog.com/job-draft-merit/)