JavaScriptの2つの型
まず本題に入る前にJavaScriptには2つの型があります。
プリミティブ型: 数値・文字列・論理値・null・undefined
オブジェクト型: その他オブジェクト
そして、上記の2つではコピーする時のJavaScript内のメカニズムが多少異なります。
簡単な例を紹介します。
プリミティブ型
let string = 'foo'
let newString = string
newString = 'bar'
console.log(string, newString);// foo bar
↑プリミティブ型では変数などはパソコンのメモリに保存され、コピーする際にも新しいメモリ空間を確保して保存します。
そのため元のstringにも影響ありません。
オブジェクト型
let object = { name: 'foo' }
let newObject = object
newObject.name = 'bar'
console.log(object, newObject);// {name: 'bar'} {name: 'bar'}
↑オブジェクト型では新しいメモリに保存するのではなく、メモリアドレスを渡します。そのため元のobjectとnewObjectが同じメモリに保存されていて同じデータを共有しています。
だからnewObjectを変更すると元のobjectの値まで変わってしまいます。
次から本題に入っていきます。
破壊的メソッドとは
対象となるオブジェクト型の元の配列の値を変えてしまうメソッドを指します。
破壊的メソッド一覧
sort()
splice()
push()
shift()
unshift()
reverse()
このメソッドの問題点は以下のミスが起きやすい点にあります。
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]
以上のことから破壊的メソッドは使用してはいけない風潮になっているらしいです。