JavaScriptの並び替えはsort()ではなくtoSorted()がオススメ

sort()とは

sort()はArrayのメソッドで、配列をソートし、ソートされた同じ配列の参照を返します。

sort()は元の配列を変更してしまうので、元の配列を変えずに使い続けたいときには不便です。

const arr = [10, 1, 5, 12]
const sortedArr = arr.sort((a, b) => a - b)
console.log(arr) // [1, 5, 10, 12]
console.log(sortedArr) // [1, 5, 10, 12]

※ sort()は数値の配列にarr.sort()で使用すると昇順にならないので、arr.sort((a, b) => a - b) にしてあります。

元の配列を変えたくない場合はslice()を間に入れるか、スプレッド構文で元の配列が変更されないようにすることが多いですが、コードが多少冗長になります。

const arr = [10, 1, 5, 12]
const sortedArr = arr.slice().sort((a, b) => a - b)
console.log(arr) // [10, 1, 5, 12]
console.log(sortedArr) // [1, 5, 10, 12]
const arr = [10, 1, 5, 12]
const sortedArr = [...arr].sort((a, b) => a - b)
console.log(arr) // [10, 1, 5, 12]
console.log(sortedArr) // [1, 5, 10, 12]

toSorted()とは

toSorted()はArrayのメソッドで、元の配列を変えずにソートして返します。

使い方はsort()と同じで違いは元の配列を変えるかどうかだけです。

比較的新しいメソッドなので、ご存知の方はまだ少ないようです。

const arr = [10, 1, 5, 12]
const sortedArr = arr.toSorted((a, b) => a - b)
console.log(arr) // [10, 1, 5, 12]
console.log(sortedArr) // [1, 5, 10, 12]

元の配列の順序を変えてしまうと、再利用した際に予期しない問題が発生する可能性があるので、並び替えをする際はtoSorted()を使用することをオススメします。

toSpliced()やtoReverted()のメソッドもある

splice()やreverse()も元の配列を変えてしまいますが、この2つにもtoSpliced()とtoReverted()が用意されているので、こちらを使用すれば元の配列を変えずにメソッドを使用できます。

splice()はそのまま使用すると元の配列の内容も変えてしまいます。

さらに、splice()だと定数や変数に代入できずに空配列になってしまいます。

const arr = [10, 1, 20, 12]
const splicedArr = arr.splice(1, 0, 7)
console.log(arr) // [10, 7, 1, 20, 12]
console.log(splicedArr) // []

スプレッド構文を使用して複製すれば元の配列は変えずに済みますが、少し冗長です。

const arr = [10, 1, 20, 12]
const splicedArr = [...arr]
splicedArr.splice(1, 0, 7)
console.log(arr) // [10, 1, 20, 12]
console.log(splicedArr) // [10, 7, 1, 20, 12]

toSpliced()を使用すればスプレッド構文で複製せずに処理できます。

const arr = [10, 1, 20, 12]
const splicedArr = arr.toSpliced(1, 0, 7)
console.log(arr) // [10, 1, 20, 12]
console.log(splicedArr) // [10, 7, 1, 20, 12]

toReverted()も同様に元の配列を変えずに処理できます。

const arr = [1, 2, 3]
const reversedArr = arr.toReversed()
console.log(reversedArr) // [3, 2, 1]
console.log(arr) // [1, 2, 3]

const reverseArr = arr.reverse()
console.log(reverseArr) // [3, 2, 1]
console.log(arr) // [3, 2, 1]

with()で指定した要素の値を変更する

toSpliced()を使用すると指定した要素の値を変更することもできますが、変更する値が1つだけであればwith()を使用したほうが、コードがシンプルになります。

const arr = [1, 2, 3, 4, 5]
const splicedArr = arr.toSpliced(2, 1, 7)
console.log(splicedArr) // [1, 2, 7, 4, 5]

const withArr = arr.with(2, 99)
console.log(withArr) // [1, 2, 99, 4, 5]

まとめ

元の配列の内容を変えると、それが原因でバグが発生することがあります。

特に理由がなければsort()などではなく、元の配列の内容を変えないtoSorted()などの使用をオススメします。