- 前回のPart1同様にJavaScriptの新たな気づきや重要だと感じた点をまとめる。
破壊的、非破壊的なメソッドについて
- 参照するデータに対して直接的な変更が入るメソッドは破壊的メソッドに分類される 。
例1
const array = ["A", "B", "C"];
console.log(array);
>> ["A", "B", "C"];
const addedArray = array.push("D");
// pushメソッドは指定した配列に引数を加えるメソッド
console.log(array);
>> ["A", "B", "C", "D"];
// 配列arrayに直接的な変更が入っている。
- 対して参照するデータに対して直接的な変更が入らないメソッドは非破壊的メソッドに分類される。
例2
const array = ["A", "B", "C"];
console.log(array);
const newArray = array.concat("D");
// concatメソッドは指定した配列をコピーしたものに引数を結合させるメソッド
console.log(newArray);
>> ["A", "B", "C", "D"]
console.log(array);
>> ["A", "B", "C"]
// 配列arrayに対して直接的な変更が入っていない
- JavaScriptにおける破壊的、非破壊的メソッドはメソッド名から区別できず、破壊的メソッドは意図しない動作(副作用)が起こりうる。
そのため破壊的メソッドか否かは開発時点で引数にした配列に対してconsole.logメソッド等で確認する必要がある。
対策として破壊的メソッドでプログラムを記述した際は破壊的メソッドである旨を
コメントアウトすることで問題発生時の切り分けを手助けするとよい。
例3
const removeIndex = (array, index) => {
array.splice(index, 1);
// spliceメソッドは配列arrayの指定したindexに対応したデータのみを削除した配列を返す
return array;
}
const array = ["A", "B", "C"];
console.log(array);
>> ["A", "B", "C"]
// この時点では配列arrayにremoveIndex関数を実行していないためすべての要素が返ってくる。
const newArray = removeIndex(array, 1);
// 変数newArrayにremoveIndex関数の実行結果を定義。
console.log(newArray);
>> ["A","C"]
// removeIndex関数によってarray[1]が削除されるconsole.log(array);
>> ["A","C"]
/* spliceメソッドは配列に対して破壊的な変更を加えるため、
removeIndex関数によって配列arrayにも影響を及ぼす。*/
- もう一つの対策は破壊的メソッドの引数に予め非破壊的メソッドでコピーした配列を指定することである。
例4
const removeIndex = (array, index) => {
array.splice(index, 1);
return array;
}
const array = ["A", "B", "C"];
const copiedArray = array.concat();
// concatメソッドは引数なしだと指定した配列(今回ならarray)をコピーしてくれる。
console.log(array);
>> ["A","B","C"]
console.log(copiedArray);
>> ["A","B","C"]
const newArray = removeIndex(copiedArray, 1);
// removeIndex関数の引数にconcatメソッドでコピーした配列を指定。
console.log(newArray);
>> ["A","C"]
// copiedArray[1]を削除した配列が返ってくる
console.log(array);
>> ["A","B","C"]
// 配列arrayに対してはremoveIndex関数を実行していないため副作用なし。
メソッドチェーン
- 配列に対してメソッドを連続して行うこと。
メソッド毎に変数に対して結果を定義する手間を省くことができる。
例5
const array = [
{ name: "Tanaka", age: 10 },
{ name: "Suzuki", age: 12 },
{ name: "Kobayashi", age: 20 },
{ name: "Takeuchi", age: 33 },
];
const sortAge = array
.filter(data => data.age <= 15);
// filterメソッドで配列array内のageが15以下のオブジェクトを抽出。
.map(data => data.name);
// filterメソッドで抽出されたarrayに対してmapメソッドで指定したプロパティを取得。
console.log(sortAge);
>> ["Tanaka", "Suzuki"]
// ageが15以下のオブジェクトのnameを取得。
- 複数の処理をメソッドチェーンで一連の処理として記述することができるが、
記述が長くなりすぎると可読性が落ちるため適度な単位(段落)をメソッドチェーンで
記述することを意識する必要がある。
(処理1〜30 => 処理(1〜10)、処理(11〜20)、処理(21〜30)で区分けするイメージ)