logologo
JavaScriptにおける関数型プログラミングとは?概要を紹介
thumb_javaskan_01
JavaScriptにおける関数型プログラミングとは?概要を紹介
アンドエンジニア編集部
2024.07.13
この記事でわかること
JavaScriptに関数型プログラミングの概念を採用する動きが活発化している
関数型プログラミングはコードが読みやすく、デバッグやテストが容易になるメリットがある
命令型プログラミングと関数型プログラミングの長短を見極め、状況に応じて選択すると良い

JavaScriptにおける関数型プログラミング

img_javaskan_01

近年、Web開発においてJavaScriptがますます重要な役割を果たす中、関数型プログラミングの概念を取り入れる動きが活発化しています。

従来の命令型プログラミング(オブジェクト指向プログラミング)とは異なり、関数型プログラミングはコードの読みやすさや保守性を向上させ、複雑なシステム開発にも柔軟に対応できる利点があります。

本記事では、JavaScriptにおける関数型プログラミングの特徴、メリットなどについて詳しく解説します。さらに、具体的なコード例を用いて、関数型プログラミングの主要な概念である「ファーストクラス関数」、「高階関数」、「クロージャ」などをわかりやすく紹介します。

【参考】:JavaScript | MDN

JavaScriptでできること9選!向いている人や学習方法も解説
プログラミングの関数とは?役に立たない?学び方と実務で役立つスキル

そもそも関数型プログラミング言語とは?

関数型プログラミングは、プログラムを関数という基本的な構成要素で組み立てていくプログラミング手法で、宣言型プログラミング言語の1種です。関数とは、名前と処理内容を定義したプログラムのまとまりであり、引数を受け取って値を返すという特徴を持ちます。

代表的な言語としてはHaskellやScalaがあります。関数型プログラミングでは、以下の4つの基本原則に基づいてプログラムを設計します。

1.状態不変性 関数は常に同じ入力に対して同じ出力を返すように設計されます。つまり、関数の内部状態は実行ごとに変化せず、常に一定の状態を保ちます。

2. 副作用の排除 関数は副作用を起こさないように設計されます。つまり、関数の処理は外部のデータや状態を変更せず、関数内部のみで完結します。

3.再帰 問題をより小さな同じような問題に分解し、それを繰り返し解決することで複雑な問題を解きます。

4. 高階関数 関数を引数として受け取ったり、関数を出力として返したりするような、関数を扱う関数を指します。

書籍「関数型言語で学ぶプログラミングの基本」

これを機会に関数型プログラミング言語について学んでみたい方に、おすすめの書籍を紹介します。関数型プログラミングは、プログラムを関数の組み合わせとして捉えるスタイルです。本書ではOCamlを用いて、関数型プログラミングの基礎と応用について詳しく解説しています。

OCamlは直感的な文法と高度な抽象化機能を備え、複雑なアプリケーションの開発に適しています。関数型プログラミングの理解を深め、他の言語でも応用できるプログラミングスキルを身につけることができるでしょう。

▪著者:川井 俊輝 ▪出版社:インプレス ▪ページ数:130ページ ▪発売日:2024/02/23

【参考】:関数型言語で学ぶプログラミングの基本

JavaScriptの関数の種種

JavaScriptにおける関数型プログラミングは、1990年代後半から徐々に注目され始めました。

JavaScriptは、関数型プログラミングの主要な概念をサポートしており、関数型プログラミングスタイルで記述することができます。

具体的には、以下のような機能が提供されており、これらの機能によってJavaScriptでも関数型プログラミングの主要な概念を実装することが可能になりました。また、JavaScriptは動的型付け言語であることから、関数に型指定ができません。

型推論の仕組みによって。ある程度は型を推論できますが、プログラムが複雑になると型が推論されないケースもあります。こうした問題を解決する方法として、静的型付け言語であるTypeScriptを使用する方法があります。以下、JavaScriptの主な関数の種類について紹介します。

1.ファーストクラス関数 関数は値として扱われ、他の変数に代入したり、関数引数として渡したり、関数から返したりすることができます。

2.高階関数 JavaScriptには、map、filter、reduceなどの高階関数が標準で用意されており、これらの関数を利用することで、より簡潔で表現力豊かなコードを書くことができます。

3.クロージャ  クロージャは、関数とその関数内で定義された変数を組み合わせたものです。関数を実行した後でも、関数内で定義された変数にアクセスすることができます。

TypeScriptとは?JavaScriptとの違いも解説!

JavaScriptにおける関数型プログラミングのメリット

img_javaskan_02

以上、関数型プログラミングとは何かについて解説しましたが、これらの原則を徹底することで、JavaScriptでは以下のようなメリットが得られます。

コードの読みやすさと理解のしやすさ

 関数は独立した単位として扱われるため、コード全体を俯瞰しやすくなり、複雑な処理であってもコードが読みやすく、理解しやすくなります。

デバッグの容易さ

関数は副作用を起こさないため、コードのどの部分でエラーが発生しているのかを特定しやすくなるため、エラーを見つけやすくデバッグが容易になります。

テストの容易さ

関数は純粋な関数であるため、入力値に対して常に同じ出力を返すことが保証されるため、テストが容易になります。

モジュール性の向上

関数は再利用可能な部品として扱われるため、コードのモジュール性を高め、保守性を向上させることができます。

関数型プログラミングの主要な概念

img_javaskan_03

JavaScriptにおける関数型プログラミングの主要な概念とプログラミング例について、具体的に見ていきましょう。

純粋関数

JavaScriptにおける関数は、functionキーワードを使って定義されます。関数は、名前、引数リスト、関数本体で構成されます。

例:平方数を計算する純粋関数 この関数は、引数 x の値のみを参照して、平方数を計算し、その値を返します。外部状態を参照したり、グローバル変数を変更したりしないため、純粋関数と言えます。

function square(x) {
  return x * x;
}
const result = square(5); // 25

イミュータブルなデータ

イミュータブルなデータとは、一度作成されたオブジェクトの状態(中身)が変わらないことを指します。具体的には、オブジェクトのプロパティを操作しても、作成されたオブジェクトの中身が変わらない(影響を受けない)状態のことです。

例:イミュータブルな配列を使って合計値を求める このコードでは、numbers配列をイミュータブル(変更不可)なデータとして扱っています。reduce関数は、配列の各要素に対して処理を行い、その結果を新たな配列として返します。元のnumbers配列は変更されません。

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // 15

高階関数

高階関数は、関数を引数として受け取ったり、関数を出力として返したりする関数のことを指します。JavaScriptには、map、filter、reduceなどの高階関数が標準で用意されています。

例:map 関数を使って配列の要素を2倍にする このコードでは、map関数を使ってnumbers配列の各要素を2倍にしています。map関数は、配列の各要素に対して処理を行い、その結果を新たな配列として返します。

const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.map(num => num * 2);
console.log(doubledNumbers); // [2, 4, 6, 8, 10]

再帰関数

関数の中で自分自身を呼び出す関数のことを指します。再帰的なアプローチを使用することで、問題をより小さな部分に分割し、それらの部分を組み合わせて問題全体を解決することができます。

例:再帰を使って階乗を計算する この関数は、再帰を使って階乗を計算します。再帰とは、関数が自分自身を呼び出す手法です。この例では、factorial(n)関数はnが0になるまで自分自身を呼び出し、その結果を掛け算して返します。

function factorial(n) {
  if (n === 0) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}
const result = factorial(5); // 120

関数の合成

複数の関数を組み合わせて新しい関数を作る手法です。JavaScriptでは、パイプ演算子 (|) を用いて関数の合成を記述することができます。

例:パイプ演算子を使って配列の要素を2倍にして合計値を求める この例では、map関数とreduce 関数を連結して、配列の要素を2倍にして合計値を求めています。

const numbers = [1, 2, 3, 4, 5];

const result = numbers
  .map(num => num * 2)
  .reduce((total, num) => total + num, 0);
console.log(result); // 30

JavaScriptの関数型プログラムと命令形プログラムの根本的な違い

img_javaskan_04

ここまで、JavaScriptにおける関数型プログラミングについて解説してきましたが、では従来の命令形プログラムと根本的に何が違うのでしょうか。JavaScriptにおける関数型プログラムと命令形プログラムは、設計思想とデータの扱い方に根本的な違いがあります。それぞれ見てみましょう。

設計思想

最初に、関数型プログラムと命令形プログラムの設計思想における違いを見てみましょう。

【命令型プログラム】 命令形プログラムは、状態と呼ばれる変数を用いてプログラムを記述します。プログラムは、状態を変化させる命令を逐次実行することで処理を進めます。

let count = 0;
for (let i = 0; i < 10; i++) {
  count++;
}
console.log(count); // 10

上記の例では、countという変数に状態を保持し、ループ内で状態を更新することで、1から10までの合計値を出力しています。

【関数型プログラム】 一方、関数型プログラムは、関数を基本的な構成要素としてプログラムを記述します。関数は、引数を受け取って値を返すというシンプルな定義を持ちます。

function add(x, y) {
  return x + y;
}
const result = add(3, 5);
console.log(result); // 8

上記の例では、addという関数を定義し、2つの引数を受け取ってそれらを足した値を返しています。

データの扱い方

次に、関数型プログラムと命令形プログラムのデータの扱い方の違いについて見てみましょう。

【命令型プログラム】 命令形プログラムでは、変数は可変であり、プログラムの実行中に値が変化します。この可変性が、プログラムの複雑さや予期せぬ動作の原因となることがあります。

let count = 0;
function increment() {
  count++;
}
increment();
increment();
console.log(count); // 2

上記の例では、increment関数を呼び出すたびにcount変数の値が1ずつ増えます。しかし、このプログラムを実行した結果が常に2になるとは限りません。例えば、別の場所でcount変数の値を変更した場合、このプログラムの出力は変化します。

【関数型プログラム】 関数型プログラムでは、変数は不可変であり、1度代入された値は変更できません。この不可変性が、プログラムの理解しやすさと信頼性を高めます。

function add(x, y) {
  return x + y;
}
const result = add(3, 5);
console.log(result); // 8

上記の例では、add関数内で変数の値を変更することはできません。そのため、常に同じ引数に対して同じ出力を返す純粋関数となります。

■ 命令型プログラムと関数型プログラムの比較 このように、JavaScriptにおける関数型プログラムと命令形プログラムは、根本的な違いを持つパラダイムです。それぞれの利点と欠点を理解した上で、状況に応じて適切なプログラミング手法を選択することが重要です。以下、比較表で整理してみました。

【命令型プログラム】 ・設計思想:状態の更新 ・データの扱い方:可変 ・利点:シンプル ・欠点:複雑になりやすく、予期せぬ動作が起こりやすい

【関数型プログラム】 ・設計思想:関数の組み合わせ ・データの扱い方:不可変 ・利点:理解しやすく信頼性が高い ・欠点:慣れないと記述が難しい

関数型プログラミングの理解を深めてスキルアップを

img_javaskan_05

ここまで JavaScript における関数型プログラミングについて解説しました。近年では、ReactやReduxなどのJavaScriptフレームワークも関数型プログラミングの概念を取り入れており、Web開発における関数型プログラミングの重要性はますます高まっています。

JavaScript開発では関数型プログラミングの思想によって、より柔軟で保守性の高いコードを書くことができるようになります。ぜひ関数型プログラミングの習得にチャレンジしてみましょう。

JavaScriptの数値計算とは?演算子やライブラリの例を紹介
気になる人のXをフォローしよう!
公式LINE
公式YouTube
マイナビITエージェント

編集部オススメコンテンツ

Sponsored
【年収±診断】6つの質問に答えて、真の市場価値をチェック!
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

お問い合わせ・情報提供
はじめて転職される方へ
SE・システムエンジニア(IT/通信/インターネット) 求人一覧

編集部おすすめコンテンツ

Sponsored
【年収±診断】6つの質問に答えて、真の市場価値をチェック!
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

logologo
Powered by マイナビ AGENT