Array.prototype.toSorted() 因需要创建数组副本,内存占用通常高于原地排序的 sort(),运行时间在大多数业务场景下差异可忽略,但在超大数组或内存敏感场景需警惕复制开销。
先说结论:toSorted() 牺牲少量性能换取数据安全性,适合 React 等不可变数据场景,不适合超大数组高频排序。
- 适合:前端状态管理、函数式编程、需要保留原数组的场景
- 重点看:数组长度、内存限制、浏览器兼容性(Chrome 117+、Node 20+)
- 别忽略:toSorted() 是浅拷贝,对象数组元素引用仍共享,修改元素属性会影响原数组
命令速用版
直接调用 toSorted() 获取新数组,原数组不变;sort() 直接修改原数组并返回引用。
const arr = [3, 1, 2]; const sorted = arr.toSorted((a, b) => a - b); // 新数组 [1, 2, 3] console.log(arr); // 原数组 [3, 1, 2] const arr2 = [3, 1, 2]; const sorted2 = arr2.sort((a, b) => a - b); // 原数组被修改为 [1, 2, 3]
为什么会这样
toSorted() 性能开销主要来自数组复制,而非排序算法本身。
sort() 是原地算法(In-place),直接在原内存空间交换元素,额外内存分配少。toSorted() 必须先分配新内存空间复制原数组元素,再对新数组排序。公开资料中没有看到可靠的量化数据证明具体慢多少,但 V8 引擎文档提到底层实现可能对小数组做了 fast-path 优化,意味着在小数据量下性能损耗可能极低。
分步处理
根据数据规模和场景选择方法,避免盲目替换。
第一步:判断数据规模
如果数组长度小于 1000 项,toSorted() 的复制开销在现代设备上通常小于 1ms,可优先保证代码安全性。如果数组超过 10 万项,需警惕内存峰值。
第二步:检查兼容性
toSorted() 是 ES2023 特性。Chrome 117+、Firefox 120+、Safari 17.4+、Node.js 20.2+ 原生支持。旧环境需降级:
const sorted = arr.toSorted?.((a, b) => a - b) ?? [...arr].sort((a, b) => a - b);
第三步:确认对象引用
如果数组元素是对象,toSorted() 仅复制引用。修改 sorted[0].name 仍会影响原数组对应项。需深拷贝时才用 structuredClone 等方案。
怎么验证是否生效
使用 Performance API 本地测试具体耗时,不要依赖理论数据。
console.time('toSorted');
const s1 = largeArray.toSorted((a, b) => a - b);
console.timeEnd('toSorted');
console.time('sort');
const s2 = [...largeArray].sort((a, b) => a - b);
console.timeEnd('sort');对比两者耗时差值。如果差值稳定超过业务阈值(如 50ms),则在大数组场景回退到 sort() 配合展开运算符。
常见坑
兼容性报错:旧浏览器或 Node.js 18 及以下会报 TypeError: arr.toSorted is not a function,必须加降级处理。
浅拷贝陷阱:以为 toSorted() 是深拷贝,修改对象属性导致原数据污染。它只保证数组顺序不变,不保证元素内容隔离。
默认排序陷阱:不传比较函数时,toSorted() 默认按字符串 Unicode 码点排序,数字数组 [10, 2] 会变成 [10, 2] 而非 [2, 10],必须显式传 (a, b) => a - b。
常见问题
toSorted 比 sort 慢多少?
公开资料中没有看到可靠的量化数据,通常慢在数组复制环节,小数组差异可忽略。
React 中必须用 toSorted 吗?
不是必须,但推荐。它能避免直接修改 state 数组导致的渲染异常,符合不可变数据原则。
旧浏览器怎么兼容 toSorted?
使用 [...arr].sort() 替代,或引入 core-js polyfill,但需检测是否已存在该方法。
toSorted 支持对象数组排序吗?
支持,但必须传比较函数,如 (a, b) => a.price - b.price,否则按字符串排序会出错。
参考来源
- ECMAScript 2023 新特性文档,Array.prototype.toSorted 方法说明
- 浏览器兼容性文档,Chrome 117+、Firefox 120+、Safari 17.4+ 支持情况
- 知识库资料:如何用 Array.prototype.toSorted() 在不改变原始数据顺序的前提下获取排序后的新副本
- 知识库资料:如何利用 Array.prototype.toSorted()(ES2023) 实现符合 React 声明式更新的排序