sort-toSorted
JS sort vs toSorted
在 JS 裡常會聽到「原地排序 sort」跟「回傳新陣列的 toSorted」這兩種說法,其實核心差別只有幾個關鍵點:有沒有改原本的陣列、回傳值是誰、以及能不能鏈式使用。
1. 名稱先釐清:現在標準叫 toSorted
- 舊文章裡常看到的
sorted:- 多半只是作者自訂的 helper 函式名稱(例如
const sorted = arr.slice().sort(...))。 - JavaScript 標準裡 沒有 內建叫
sorted的方法。
- 多半只是作者自訂的 helper 函式名稱(例如
- ES2023 之後的標準方法是
Array.prototype.toSorted:- 語意就是「回傳排序後的新陣列」。
- 舊瀏覽器不支援時,才會用「自訂 sorted 函式」來 polyfill。
底下為了對齊你之前看到的說法,會用:
sort:指Array.prototype.sorttoSorted/ 「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或自訂sortedhelper。
- 要保留原資料、方便除錯、避免不小心改到共享 state → 用
- 團隊習慣:
- 如果團隊明確走 immutable 風格,建議直接 統一使用
toSorted/sorted風格,只在效能特別敏感的地方才改成sort。
- 如果團隊明確走 immutable 風格,建議直接 統一使用
一句話總結:
sort:就地改、節省記憶體,但有副作用。
toSorted/ sorted 風格:不改原資料、容易推理,但多一份陣列。