JavaScriptのトレンドは「イミュータブル」
先日、JavaScript/TypeScript実力教科書を執筆された方々のイベント[1]に参加した際、繰り返し登場したのが イミュータブル というキーワードでした。
イミュータブルとは何か、なぜ今トレンドなのか、JavaScriptでどう扱えばいいのかについて整理します。
イミュータブルとは
イミュータブル(immutable)とは「不変の」「変更できない」という意味で、 "一度作成したデータを直接変更しない" という性質を指します。
JavaScriptではオブジェクトや配列は基本的にミュータブル(可変)ですが、
イミュータブルな設計では、既存の値を変更せず新しい値を生成する形を取ります。
例:
const array = [1, 2, 3];
// ミュータブル
array.push(4);
// イミュータブル
const newArray = [...array, 4];
配列そのものを書き換えるのではなく、新しい配列を生成しています。
なぜイミュータブルが重視されるのか
1. 破壊的変更はバグの原因になりやすい
ミュータブルなコードでは、「どこで値が変わったか」が追いづらくなります。
function updateUser(user) {
user.name = "Hanako";
}
const user = { name: "Taro" };
updateUser(user);
console.log(user.name); // Hanako
呼び出し元では値を変更していないつもりでも、
関数内部で書き換えられていると、意図しないバグにつながりやすくなります。
イミュータブルにしておけば、「この値は変わらない」という前提でコードを読めるため、安全性が高まります。
2. パフォーマンス最適化がしやすい
最近のJavaScript仕様を見ると、ECMAScriptとして導入・検討されている新しい型や仕組みではイミュータブル前提の設計が増えています。
例:
- Temporal(新しい日時API)
- Composites
- Immutable ArrayBuffer
- Decimal
これらは「データが変更されない」前提で設計されており、内部最適化や並列処理と相性が良くなっています。
可変なデータは「いつ変わるかわからない」ため、JavaScriptエンジン[2]側は安全確認のためのチェック処理を省略できず、最適化が難しくなります。
3. JavaScriptの書き方自体が変化している
JavaScriptの書き方も、次第に
- クラス中心
- ミュータブル前提
から、
- 関数型スタイル
- イミュータブル志向
へとシフトしています。
配列メソッドにも明確な違いがあります。
| 種類 | メソッド |
|---|---|
| ミュータブル | push / pop / splice / sort / reverse |
| イミュータブル | map / filter / concat / slice / toSorted |
ミュータブルは悪?
ミュータブルは悪かというと、必ずしもそうではありません。
大量データ処理や低レイヤーでは、意図的にミュータブルを使うこともあります。
ただし、
基本はイミュータブル、必要な場面だけミュータブル
という思想が今のJavaScriptでは主流になっているようです。
まとめ
- イミュータブルは「値を直接書き換えない」考え方
- JavaScriptの仕様設計もイミュータブル志向になっている
- Reactなどの宣言的UIと非常に相性が良い
- 状態管理が安全になり、見通しが良くなる
ChromeやNode.jsなどでJSを実行している実行環境(V8など) ↩︎