関数・メソッド

【JavaScript】Arrayのsort()とtoSorted()の違い

更新日:2023/06/22

ECMAScript2023で配列(Arrayオブジェクト)にtoSorted()が追加されました。
これは配列をソートするメソッドですが、ソート関数としてsort()が以前からあります。
この二つの関数は、何が違うのかお伝えします。

 

引数は同じ

ECMAScriptの仕様では、二つのメソッドは次のように定義されています。

sort()の定義

Array.prototype.sort ( comparefn )

toSorted()の定義

Array.prototype.toSorted ( comparefn )

この二つの関数は、二つの値を受け取って差分を返す比較関数を引数として受け取ります。
比較関数はどちらも同じ仕様です。

比較関数については別のページで紹介しているので、そちらを読んでみてください。

 

戻り値も同じ

sort()とtoSorted()はどちらも、比較関数で比較した結果をもとに配列をソートして、その結果を返します。
そのため、元の配列と比較関数が同じなら、結果も同じです。

const ary1 = [2,1,3];
const ary2 = [2,1,3];

console.log( ary1.sort((a,b)=>a-b) );     // 結果: [ 1 , 2 , 3]
console.log( ary2.toSorted((a,b)=>a-b) ); // 結果: [ 1 , 2 , 3]

ただし、ArrayLikeなオブジェクトを適用した場合、二つのメソッドの結果が異なります。

 

破壊と非破壊

実はsort()は、とても困る性質があります。
それは、元の配列の内容を変更(破壊)してしまうものです。

const ary1 = [2,1,3];
console.log( ary1.sort((a,b)=>a-b) ); // 結果: [ 1 , 2 , 3]
console.log( ary1 );     // 結果: [ 1 , 2 , 3] ← 元の配列の内容が変わってしまった

一方のtoSorted()は、元の配列の内容を変更しません(非破壊)。

const ary2 = [2,1,3];
console.log( ary2.toSorted((a,b)=>a-b) ); // 結果: [ 1 , 2 , 3]
console.log( ary2 );     // 結果: [2,1,3] ← 元の配列の内容と同じ

toSorted()実装前は、元の配列の内容を保持したいときArray.from()などでコピーする必要がありました。

const ary1 = [2,1,3];
console.log( Array.from( ary1 ).sort((a,b)=>a-b) ); // 結果: [ 1 , 2 , 3]
console.log( ary1 );  // 結果: [2,1,3]

toSorted()を使うことで、少しだけ手間が減らせそうですね。

 

ArrayLikeなオブジェクトの対応が違う

どちらもArrayLikeなオブジェクトをthis値として渡すことができます。

ArrayLikeなオブジェクトとは、lengthプロパティを持つオブジェクトです。
■参考記事:【JavaScript】 アレイライク・配列風・配列のようなオブジェクトとは

しかし、ソート後の戻り値が異なります。
sort()は、元となるオブジェクトの中身を入れ替えたものを返します。
toSorted()は、Arrayオブジェクトを返します。

const aryLike1 = {0:0,1:100,2:2,3:300,4:4,5:5,a:"a",length:6};
const aryLike2 = {0:0,1:100,2:2,3:300,4:4,5:5,a:"a",length:6};

console.log( Array.prototype.sort.call( aryLike1 , (a,b)=>a-b ) );
  // 結果: {0: 0, 1: 100, 2: 2, 3: 300, 4: 4, 5: 5, a: 'a', length: 6}

console.log( Array.prototype.toSorted.call( aryLike2 , (a,b)=>a-b ) );
  // 結果: [0, 100, 2, 300, 4, 5]

上の例を見ると、sort()の結果に元のオブジェクトに含まれている数値以外のプロパティが残っています。
toSorted()は数値プロパティのみが残っています。

二つのメソッドの大きな違いですね。
ArrayLikeなオブジェクトをソートすることはあまり無いですが…

call()については、次のページを読んでみてください。
【JavaScript】 そろそろcall()とapply()を理解してみようと思う

 

FireFoxは未実装

2023年6月の時点で、FireFoxはtoSorted()が実装されていないようです。
ブラウザで使用するのは、もう少し待つ必要がありますね。

更新日:2023/06/22

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。