😎
【JavaScript】破壊的メソッドの非破壊的な書き方
破壊的メソッドの何がまずいのか?
破壊的メソッドを使うとコードの読み手に混乱を与えてしまう可能性があります。
破壊的メソッドを使った例
const numbers = [1, 2, 3, 4, 5];
// とても長い処理
numbers.push(6); <- 読み飛ばされてしまう可能性が高い
// とても長い処理
console.log(numbers); <- 読み手は[1, 2, 3, 4, 5]を期待している
// 実際は[1, 2, 3, 4, 5, 6];
非破壊的メソッドを使った例
const numbers = [1, 2, 3, 4, 5];
// とても長い処理
const newNumbers = numbers.concat(6);
// とても長い処理
console.log(numbers); // [1, 2, 3, 4, 5] 読み手の期待通りのまま
console.log(newNumbers); // [1, 2, 3, 4, 5, 6]
結論
スプレッド構文を使えばOK!
以下、具体的な書き方と別の書き方をまとめます。
push()
push() メソッドは、配列の末尾に 1 つ以上の要素を追加することができます。また戻り値として新しい配列の要素数を返します。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.push(6);
console.log(numbers); // [1, 2, 3, 4, 5, 6]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
const newNumbers = [...numbers, 6];
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [1, 2, 3, 4, 5, 6]
// concat()
const numbers = [1, 2, 3, 4, 5];
const newNumbers = numbers.concat(6);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [1, 2, 3, 4, 5, 6]
unshift()
unshift() メソッドは、配列の最初に 1 つ以上の要素を追加し、新しい配列の長さを返します。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.unshift(0);
console.log(numbers); // [0, 1, 2, 3, 4, 5]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
const newNumbers = [0, ...numbers];
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [0, 1, 2, 3, 4, 5]
// concat()
const numbers = [1, 2, 3, 4, 5];
const newNumbers = [0].concat(numbers);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [0, 1, 2, 3, 4, 5]
pop()
pop() メソッドは、配列から最後の要素を取り除き、その要素を返します。このメソッドは配列の長さを変化させます。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.pop();
console.log(numbers); // [1, 2, 3, 4]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
const newNumbers = [...numbers];
newNumbers.pop()
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [1, 2, 3, 4]
// slice()
const numbers = [1, 2, 3, 4, 5];
const newNumbers = numbers.slice(0, 4);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [1, 2, 3, 4]
shift()
shift() メソッドは、配列から最初の要素を取り除き、その要素を返します。このメソッドは配列の長さを変えます。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.shift();
console.log(numbers); // [2, 3, 4, 5]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
const newNumbers = [...numbers];
newNumbers.shift();
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [2, 3, 4, 5]
// slice()
const numbers = [1, 2, 3, 4, 5];
const newNumbers = numbers.slice(1, 5);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [2, 3, 4, 5]
sort()
sort() メソッドは、配列の要素を in place でソートします。既定のソート順は昇順で、要素を文字列に変換してから、UTF-16 コード単位の値の並びとして比較します。
破壊
const numbers = [5, 1, 4, 2, 3];
numbers.sort();
console.log(numbers); // [1, 2, 3, 4, 5]
非破壊
// スプレッド構文
const numbers = [5, 1, 4, 2, 3];
newNumbers = [...numbers].sort()
console.log(numbers); // [5, 1, 4, 2, 3]
console.log(newNumbers); // [1, 2, 3, 4, 5]
reverse()
reverse() メソッドは、配列の要素を In-place アルゴリズムで反転させます。最初の要素が最後の要素に、最後の要素が最初の要素になります。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // [5, 4, 3, 2, 1]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
newNumbers = [...numbers].reverse()
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [5, 4, 3, 2, 1]
fill()
fill() メソッドは、開始インデックス(デフォルトは 0)から終了インデックス(デフォルトは array.length)までのすべての要素を、静的な値に変更した配列を返します。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.fill(7);
console.log(numbers); // [7, 7, 7, 7, 7]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
newNumbers = [...numbers].fill(7)
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [7, 7, 7, 7, 7]
copyWithin()
copyWithin() メソッドは、サイズを変更せずに、配列の一部を同じ配列内の別の場所にシャローコピーして返します。
破壊
const numbers = [1, 2, 3, 4, 5];
numbers.copyWithin(2, 3, 5);
console.log(numbers); // [ 1, 2, 4, 5, 5 ]
非破壊
// スプレッド構文
const numbers = [1, 2, 3, 4, 5];
newNumbers = [...numbers].copyWithin(2, 3, 5);
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [ 1, 2, 4, 5, 5 ]
参考
Discussion
Qiitaの方でつっこみ入ってますね。
教えてくださりありがとうございます!修正しました。
返り値に注意しないとですね
結構まちがいますよね。