tosorted 不修改原数组,返回浅拷贝新数组;需注意对象引用共享、比较函数须显式返回-1/0/1、旧浏览器需降级处理、高频小数组调用有内存分配开销。

toSorted 不会修改原数组,但要注意它返回的是新数组
Array.prototype.toSorted 是 ES2024 新增的不可变排序方法,它的核心行为就是「不改变原数组」——这点和 Array.prototype.sort 有本质区别。sort 直接原地修改并返回原数组引用,而 toSorted 总是返回一个浅拷贝后的新数组。所以只要你没把返回值赋给原变量,原始顺序就天然保留。
常见错误是误以为需要手动复制再调用:[...arr].toSorted() 或 arr.slice().toSorted(),其实完全没必要——toSorted 内部已经做了这一步。
- 正确写法:
const sorted = arr.toSorted(),arr保持不变 - 错误习惯:
const sorted = [...arr].toSorted(),多一次无意义的展开和拷贝 - 注意:如果数组元素是对象,
toSorted只拷贝数组结构,对象引用仍共享(即浅拷贝)
自定义比较函数时,必须显式返回 -1 / 0 / 1,不能只用减法
和 sort 一样,toSorted 接收可选的比较函数,但很多人直接照搬数字数组的 (a, b) => a - b,这在字符串或混合类型下会出问题——因为减法对非数字会转为 NaN,导致排序结果不可预测(例如 ['b', 'a', 'c'].toSorted((a, b) => a - b) 实际按 NaN 排,顺序乱掉)。
真正安全的做法是用 String.prototype.localeCompare 处理字符串,或用 Math.sign 包裹数值比较:
const strings = ['banana', 'apple', 'cherry']; const sorted = strings.toSorted((a, b) => a.localeCompare(b)); // ✅ 正确 <p>const numbers = [3, 1, 4]; const sortedNums = numbers.toSorted((a, b) => Math.sign(a - b)); // ✅ 显式控制返回值</p>
- 避免
(a, b) => a > b ? 1 : -1这类漏掉===情况的写法,会导致相等元素位置不稳定 - 如果比较函数不传,默认按字符串 Unicode 码点升序,不是数值大小
IE 和旧版 Safari 不支持,需检查运行环境或加 polyfill
toSorted 在 Chrome 120+、Firefox 121+、Safari 17.4+ 才稳定支持。Node.js 需要 20.12+。如果你的项目还要兼容 IE 或 macOS Ventura 之前的 Safari,直接调用会报 TypeError: arr.toSorted is not a function。
简单兜底方案是检测 + 降级:
const safeToSorted = (arr, compareFn) => {
return typeof arr.toSorted === 'function'
? arr.toSorted(compareFn)
: [...arr].sort(compareFn);
};
- 不要用
core-js全量 polyfill,它会污染全局;优先用按需引入或 Babel 插件@babel/plugin-transform-array-prototype-to-sorted - 注意:降级到
sort时,虽然结果一致,但语义上已不是纯函数(sort修改原数组),只是你没用那个返回值而已
性能差异很小,但大量小数组反复调用时要注意内存分配
toSorted 必须创建新数组,意味着每次调用都触发一次内存分配。对几万元素的大数组,V8 引擎优化后和 sort 差距不大;但如果是高频操作(比如每帧处理上百个长度为 5~10 的数组),累积的小对象 GC 压力可能比预期高。
- 若确定后续不会再用原数组,直接
arr.sort()更省内存 - 若需多次不同规则排序(如按 name、再按 age),用
toSorted避免反复恢复原顺序更清晰 - Chrome DevTools 的 Memory 节点里可以观察
Array分配速率,验证是否真成瓶颈
真正容易被忽略的是浅拷贝语义:当你对数组里的对象做 toSorted 后再修改某个对象属性,原数组对应项也会变——这不是 toSorted 的 bug,而是 JavaScript 对象引用的自然表现。










