Array.prototype.sort() 默认按字符串 Unicode 码点排序,数字数组需传入比较函数如 a - b;对象数组按属性排序需安全取值并比较,sort() 原地修改且不保证稳定。

Array.prototype.sort() 默认按字符串 Unicode 码点排序,直接调用 sort() 对数字数组会出错,比如 [10, 2, 33] 排成 [10, 2, 33](因为 "10" 为 true)。
为什么数字数组直接 sort() 会错乱
JavaScript 的 sort() 不做类型推断,所有元素先转成字符串再比较。数字 10 → "10",2 → "2",而 "10".charCodeAt(0) 是 49,"2".charCodeAt(0) 是 50,所以 "10" 成立,10 被排在 2 前面。
常见错误现象:[5, 10, 1].sort() 返回 [1, 10, 5],不是预期的升序。
- 仅当数组全是单字符字符串或已知字典序正确时,可省略比较函数
- 任何含多位数、负数、浮点数、
null/undefined的数组,都必须传比较函数 - 比较函数返回值必须是数字:负数(a 在 b 前)、0(位置不变)、正数(a 在 b 后)
升序/降序数字排序的写法差异
升序:用 a - b;降序:用 b - a。这是最简且安全的写法,适用于整数和浮点数。
立即学习“Java免费学习笔记(深入)”;
示例:
[3, 1, 4.5, -2].sort((a, b) => a - b); // [-2, 1, 3, 4.5] [3, 1, 4.5, -2].sort((a, b) => b - a); // [4.5, 3, 1, -2]
-
a - b隐式处理了Number转换,即使数组含字符串数字(如["3", "1"]),也会被自动转为数字相减 - 但若数组混有非数字值(如
[1, "a", 3]),"a" - 1得NaN,整个排序行为未定义,结果不可靠 - 不要用
a > b或return 1 / -1—— 这类布尔或固定值返回会破坏排序稳定性
对象数组按属性排序怎么写
关键在比较函数里取到要排序的属性值,并确保它们可比(避免 undefined 导致 NaN)。
示例:按 name 字符串升序,按 age 数字升序:
const users = [{name: "Alice", age: 30}, {name: "Bob", age: 25}];
users.sort((a, b) => a.name.localeCompare(b.name)); // 字符串安全比较
users.sort((a, b) => (a.age || 0) - (b.age || 0)); // 防 undefined-
String.prototype.localeCompare()比a.name > b.name更可靠,支持多语言和大小写敏感控制 - 属性可能不存在时,用
a.prop ?? 0或a.prop || ""提供默认值,否则undefined - 5是NaN - 链式取值如
a.address?.city要配合空值判断,否则报错
sort() 是原地排序且会改变原数组
sort() 直接修改原数组,不返回新数组。如果需要保留原数组,必须先拷贝。
- 浅拷贝用
[...arr].sort(...)或arr.slice().sort(...) - 对象数组拷贝后,内部对象仍是同一引用 —— 排序不影响对象内容,但顺序变了
- 如果排序逻辑复杂或需多次使用原顺序,漏掉拷贝会导致后续逻辑出错,且不易排查
容易被忽略的一点:V8 引擎对 sort() 的实现是不稳定的(尤其在小数组或特定版本),如果依赖相同元素的相对位置不变(比如分页后合并排序),得额外加稳定排序逻辑或用 Intl.Collator 等替代方案。











