概要
関数型プログラミングは“考え方”であり、“制約”ではない。
JavaScriptでもその思想を取り入れることで、コードは明確に、状態は安全に、ロジックは再利用可能になる。
本稿では、以下の視点から関数型思考をJavaScriptへ導入する:
- 副作用(Side Effect)とその管理
- 純粋関数とテスタビリティ
- 不変性(Immutability)と構造共有
- 高階関数と関数合成
- 実用ライブラリ(Ramda, Lodash/fp等)の活用
1. 副作用(Side Effect)の定義と排除
副作用とは、関数の外部世界に影響を及ぼす操作のこと。
例:DOM操作、ログ出力、API通信、グローバル変数の変更
// ❌ 副作用あり
function saveUser(user) {
localStorage.setItem('user', JSON.stringify(user));
}
// ✅ 副作用を外に逃がす
function serializeUser(user) {
return JSON.stringify(user);
}
→ ✅ 副作用は関数外へ押し出し、純粋ロジックと処理を分離
2. 純粋関数とは?
- ✅ 同じ入力 → 同じ出力
- ✅ 外部状態に依存しない
- ✅ 外部状態を変更しない
function add(a, b) {
return a + b;
}
→ ✅ テストが簡単、再利用しやすく、構成可能
3. 不変性(Immutability)の維持
// ❌ オブジェクトを直接変更
user.name = 'Toto';
// ✅ 新しいオブジェクトを返す
const updatedUser = { ...user, name: 'Toto' };
→ ✅ データ構造を破壊せず、安全に状態管理ができる
4. 高階関数(Higher-Order Functions)
✅ 関数を“受け取る”または“返す”関数
function map(arr, fn) {
const result = [];
for (const item of arr) {
result.push(fn(item));
}
return result;
}
map([1, 2, 3], x => x * 2); // [2, 4, 6]
- ✅ 抽象化と再利用のための中核パターン
- ✅
.map
,.filter
,.reduce
もすべて高階関数
5. 関数合成(Function Composition)
✅ 関数をつなぎ、パイプライン化
const trim = (s) => s.trim();
const toUpper = (s) => s.toUpperCase();
const cleanAndUpper = (s) => toUpper(trim(s));
→ ✅ 小さな関数をつないで大きな機能を構築する
RamdaやLodash/fpの活用例
import { pipe } from 'ramda';
const cleanAndUpper = pipe(
(s) => s.trim(),
(s) => s.toUpperCase()
);
→ ✅ データフローを左→右で直感的に記述可能
6. 実用例:ユーザーの年齢フィルタ → 名前抽出 → 大文字変換
const users = [
{ name: 'toto', age: 28 },
{ name: 'momo', age: 18 },
{ name: 'kiki', age: 35 }
];
const result = users
.filter(u => u.age >= 20)
.map(u => u.name.toUpperCase());
→ ✅ 副作用なし、純粋関数による安全なデータ変換チェーン
設計判断フロー
① この関数は同じ入力で同じ出力か? → 純粋関数か確認
② 外部状態を変更していないか? → 副作用を外部へ
③ 状態を破壊していないか? → イミュータブルに扱う
④ 処理を関数で分けられるか? → 高階関数で抽象化
⑤ 合成して流れにできるか? → pipe / composeの導入
よくあるミスと対策
❌ 関数内で外部変数を更新
→ ✅ 状態を引数で受け取り、出力で返す構造に
❌ 再利用性のない巨大な関数
→ ✅ 小さな純粋関数に分解し、合成する設計へ
❌ map内で副作用操作(console, fetchなど)
→ ✅ .map()
は純粋関数だけに使うことを徹底
結語
関数型思考とは「ロジックを“構造化”し、状態を“制御可能”にする設計戦略」である。
- 副作用を隔離し
- 関数を分解し
- データを変換で流し
- 構造を組み合わせる
予測可能性、テスタビリティ、再利用性――
そのすべてが“純粋な関数”から生まれる。