目的
新卒1年目でレビュー指摘もらった箇所を理解したい。
プルリクのコメントで mutable
なコーディングを指摘された。
javascript で 配列には push
メソッドばかり使ってきた私なので immutable
の意識が欠けていたのでここで整理してみようと思った。
英語の意味
- mutable:可変
- immutable:不変
immutable
は変化しないということですね。
mutable, immutable とは?
ミュータブルオブジェクトは、オブジェクトを作成した後に状態を変更できるオブジェクトです。
イミュータブルは、オブジェクトが作成された後は状態を変更できないオブジェクトです。
- mutable = 変更可
- immutable = 変更不可
ということですね。
その中でも、プリミティブ型はイミュータブルです。
また、文字列や数値もイミュータブルです。
それに対して Array
オブジェクトや Object
オブジェクト、Date
オブジェクトなどはミュータブルなオブジェクトです。
mutable の例
array
const fruits = ['バナナ', 'いちご', 'ぶどう'];
fruits.push('シャインマスカット'); // fruits というオブジェクトが書き換えられてしまう。
cosole.log(fruits); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']
object
const user = {"id": 1, "name": "Qiita太郎", "age": 23}
user.country = 'Japan'; // user が書き換えられる
console.log(user); // output => {id: 1, name: 'Qiita太郎', age: 23, country: 'Japan'}
immutable の例
例えば、以下の例は TypeScript
という文字列を hello world
という文字列を変更しているように見えますが、 mutableString
という変数に対して、 hello world TypeScript
という文字列を再代入しているということです。
let mutableString = 'hello world';
mutableString = mutableString + 'TypeScript';
console.log(mutableString) // output => 'hello world TypeScript'
なぜ immutable を意識したほうがよいのか?
もしオブジェクトがイミュータブルであったなら、オブジェクトの複製はオブジェクト全体の複製ではなく、単に参照の複製で済む。参照は通常オブジェクト自体よりもずっと小さいので(典型的にはポインタのサイズのみ)、メモリが節約でき、プログラムの実行速度もよくなる。(wikipedia参照)
immutable
のオブジェクトは何度生成しても同じものが作成されます。
JavaScript で immutable を意識してみる
結論
なるべく破壊的メソッドの使用を控える
(禁止しろ!ということではなく、状況によって使い分けようねということです。)
破壊メソッド
splice()
push()
unshift()
pop()
shift()
sort()
reverse()
fill()
copyWithin()
破壊メソッドの使用をやめてみる
// ======
// 前述の例
// ======
const fruits = ['バナナ', 'いちご', 'ぶどう'];
fruits.push('シャインマスカット'); // fruits というオブジェクトが書き換えられてしまう。
cosole.log(fruits); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']
// ======
// スプレッド構文で書き換える
// ======
const fruits = ['バナナ', 'いちご', 'ぶどう'];
// 既存の fruits というオブジェクトを書き換えることなく、 値の書き換えに成功!
const immutableFruis = [...fruits, 'シャインマスカット'];
cosole.log(immutableFruis); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']
まとめ
いかがでしょうか?
immutable
を意識しつつ、状況によって柔軟に対応していきましょう!