Skip to main content

sort-toSorted

JS sort vs toSorted

在 JS 裡常會聽到「原地排序 sort」跟「回傳新陣列的 toSorted」這兩種說法,其實核心差別只有幾個關鍵點:有沒有改原本的陣列、回傳值是誰、以及能不能鏈式使用


1. 名稱先釐清:現在標準叫 toSorted

  • 舊文章裡常看到的 sorted
    • 多半只是作者自訂的 helper 函式名稱(例如 const sorted = arr.slice().sort(...))。
    • JavaScript 標準裡 沒有 內建叫 sorted 的方法。
  • ES2023 之後的標準方法是 Array.prototype.toSorted
    • 語意就是「回傳排序後的新陣列」。
    • 舊瀏覽器不支援時,才會用「自訂 sorted 函式」來 polyfill。

底下為了對齊你之前看到的說法,會用:

  • sort:指 Array.prototype.sort
  • toSorted / 「sorted 風格」:指「不改原陣列、回傳排序後的新陣列」的做法

2. sort就地排序(in-place)會改原本陣列

特性:

  • 直接在 原陣列上重新排順序
  • 回傳值仍是同一個陣列的參考
  • 預設是「字串排序」,數字時常需要自己給 compare 函式。
const nums = [3, 1, 2];
const sortedRef = nums.sort((a, b) => a - b);

console.log(nums); // [1, 2, 3]:原本的 nums 被改掉
console.log(sortedRef); // [1, 2, 3]:跟 nums 指向同一個陣列
console.log(nums === sortedRef); // true

適合情境:

  • 你「本來就打算」改這個陣列的內容(例如暫存資料,用完就丟)。
  • 在意效能/記憶體,用 in-place 排序可以避免多產生一份陣列。

常見地雷:

  • 以為 sort 會回傳「新陣列」,後面還拿原陣列當作「未排序版本」用,結果整個邏輯錯亂。

3. toSorted(或自訂 sorted helper):不改原本陣列,回傳新陣列

現代標準做法是用 toSorted

const nums = [3, 1, 2];
const sorted = nums.toSorted((a, b) => a - b);

console.log(nums); // [3, 1, 2]:原本的 nums 沒被改
console.log(sorted); // [1, 2, 3]:新的排序結果
console.log(nums === sorted); // false

如果環境還不支援 toSorted,會看到很多人自己做一個 sorted

const sorted = (arr, compareFn) => arr.slice().sort(compareFn);

const nums = [3, 1, 2];
const result = sorted(nums, (a, b) => a - b);

console.log(nums); // [3, 1, 2]
console.log(result); // [1, 2, 3]

特性:

  • 不會動到原本陣列(immutable 風格)。
  • 回傳新的陣列物件,很適合搭配函數式風格/React 等需要「不可變資料」的框架。

適合情境:

  • React state、Redux、Vue 的 computed 等等,只要你要「保留原資料,再拿排序結果做顯示或後續運算」。
  • 想用 map / filter / reduce 等方法鏈式處理,避免到處混進副作用。

4. sort vs toSorted(或「sorted 風格」)比較表

特性sort(in-place)toSorted / sorted 風格
是否改動原陣列✅ 會改❌ 不會改
回傳值同一個陣列的參考新的陣列
是否容易產生副作用較高,因為共享同一個陣列較低,資料流較清楚
適合場景只在當下使用、不需要再保留原順序需要保留原資料、React state 等
記憶體用量較省(不產生新陣列)較多(多一份排序後陣列)

5. 數字排序常見陷阱:sort() 預設是字串排序

不管是 sort 還是 toSorted,都一樣要注意「比較函式」的問題:

const nums = [10, 2, 5];

nums.sort(); // 或 nums.toSorted() 沒給 compareFn
// 結果會是 [10, 2, 5] → 其實是依字串 '10' < '2' < '5' 的順序

// 正確數字排序要這樣:
nums.sort((a, b) => a - b);
// 或
nums.toSorted((a, b) => a - b);

記憶口訣:

  • 有數字就給 compareFn,不要偷懶。

6. 實務小準則(怎麼選?)

  • 偏命令式流程/單純工具程式:
    • 想要直接就地排好,之後不再需要原順序 → 用 sort
  • 偏函數式/前端框架狀態管理:
    • 要保留原資料、方便除錯、避免不小心改到共享 state → 用 toSorted 或自訂 sorted helper
  • 團隊習慣:
    • 如果團隊明確走 immutable 風格,建議直接 統一使用 toSorted / sorted 風格,只在效能特別敏感的地方才改成 sort

一句話總結:

sort:就地改、節省記憶體,但有副作用。
toSorted / sorted 風格:不改原資料、容易推理,但多一份陣列。