toSorted 比 sort 更安全,因为它不修改原数组而返回新数组,避免不可变更新场景下的引用污染和渲染 bug;参数与 sort 一致,仅支持浅拷贝,不支持 thisArg,需注意兼容性与深拷贝需求。

为什么 toSorted 比 sort 更安全
sort 会直接修改原数组,而 toSorted 总是返回一个新数组,原数组完全不受影响。这在 React、Redux 或任何需要不可变更新的场景里,能避免意外的引用污染和难以追踪的渲染 bug。
常见错误现象:用 arr.sort((a, b) => a - b) 后发现其他地方引用的 arr 也变了——这不是 bug,是 sort 的设计行为。
使用场景包括:临时展示排序结果、对比前后状态、函数式链式调用(比如 filter().toSorted())。
toSorted 的参数和默认行为
它接受一个可选的比较函数,签名和 sort 完全一致:(a, b) => number。不传参时,默认按字符串 Unicode 码点升序排列,这点和 sort 一模一样。
注意:和 sort 不同,toSorted 不支持“原地修改 + 返回 this”的语义,它只返回新数组,没有副作用。
- 数字升序:
[3, 1, 4].toSorted((a, b) => a - b)→[1, 3, 4] - 字符串忽略大小写:
['Banana', 'apple'].toSorted((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())) - 对象按字段排序:
items.toSorted((a, b) => a.price - b.price)
兼容性与降级方案
toSorted 是 ES2023 新增方法,Chrome 117+、Firefox 119+、Safari 17.4+ 支持;Node.js 20.6+ 原生支持。旧环境会报 TypeError: arr.toSorted is not a function。
不建议手动 polyfill(因为无法完美复现引擎级排序稳定性),更稳妥的做法是降级为 [...arr].sort(...):
const sorted = arr.toSorted ? arr.toSorted(comparator) : [...arr].sort(comparator);
性能上,toSorted 在 V8 中做了优化,比手动展开再 sort 略快,但差异通常可忽略;真正重要的是语义清晰——你明确表达了“我要一个新数组”。
容易被忽略的陷阱
数组元素如果是对象,toSorted 只复制数组本身,不深拷贝元素。所以 sorted[0] === original[0] 仍为 true。如果你需要深拷贝后再排序,得自己组合 structuredClone 或其他方案。
另一个坑是误以为它支持 thisArg(像 map 那样),但它不支持——比较函数里的 this 就是全局对象或 undefined(严格模式),别指望用 bind 或箭头函数绕过作用域问题。
最后提醒:TypeScript 用户需确保 lib 包含 es2023,否则类型检查会报错,即使运行时有 polyfill 也不行。










