Chrome和Firefox的sort()稳定性差异取决于ES2019合规性与比较函数正确性;ES2019起强制稳定排序,但旧版浏览器及错误写法(如不返0、NaN、语义不一致)仍致不稳定;实测优于UA判断,强需求可加原始索引兜底。

Chrome 和 Firefox 的 sort() 方法在稳定性上**不是天生不同**,而是取决于两个关键因素:浏览器版本是否符合 ES2019 规范,以及你写的比较函数是否真正合规。稳定性差异往往不是“浏览器故意不一致”,而是旧版本实现 + 错误写法共同导致的。
ES2019 是分水岭:稳定排序成为强制要求
ES2019 正式规定 Array.prototype.sort 必须是稳定排序——即相等元素保持原始相对顺序。但该规范只对“新引擎”生效:
- Chrome 70+、Firefox 63+、Safari 14+、Node.js v12.0.0+ 已按规范实现稳定排序
- Safari 13 及更早版本仍用不稳定快排(哪怕传了
compareFn) - Firefox 62 或 Chrome 69 等旧版本也不保证稳定
比较函数写错,再新的浏览器也“不稳定”
稳定性只在比较结果为 0 时起作用——它告诉引擎:“这两个元素排序维度上等价,请别动它们的相对位置”。但很多常见写法会破坏这个前提:
-
(a, b) => a.id > b.id ? 1 : -1:永远不返回0,引擎无法识别“相等”,直接放弃稳定逻辑 -
(a, b) => a.value - b.value:若a.value或b.value是undefined、null、字符串,结果可能是NaN,行为未定义,各浏览器处理方式不同 -
(a, b) => a.name.localeCompare(b.name):本身稳定,但如果混用大小写敏感/不敏感逻辑,语义相等的项可能被判定为不等,间接破坏稳定性
实际验证比查 UA 更可靠
不要靠 navigator.userAgent 判断是否稳定。运行这段代码即可实测当前环境:
若返回 [0,1,2],说明当前环境对相等项保持了原始顺序,即稳定;否则就是不稳定(哪怕你用的是 Chrome 90,也可能因比较函数问题失效)。
需要强一致?加一层原始索引兜底
当业务不允许任何风险(如金融数据、多条件排序),推荐主动增强稳定性:
- 给每个元素附带原始下标:
arr.map((item, idx) => ({ item, __idx: idx })) - 主排序字段不同时按主字段;相同时按
__idx保序:(a, b) => (a.time - b.time) || (a.__idx - b.__idx) - 最后提取原数据:
.map(({ item }) => item)
这种方式不依赖浏览器实现,兼容所有环境,且开销极小。


















