Safari中嵌套数组排序的特定比较器异常问题分析
Safari中数组排序比较器混合返回数字与布尔值的异常问题分析
问题重现
这是仅在Safari中出现的特殊边界问题:当数组sort方法的比较器同时返回-1、true、false时,排序逻辑会出现异常,和仅返回true/false的同类问题表现不同。
测试代码如下:
[[1, 0], [1, 1], [0, 0], [0, 1]].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0])
不同浏览器的执行结果:
- Chrome、Firefox返回符合预期的排序结果:
[[0, 0], [0, 1], [1, 0], [1, 1]] - 宣称支持稳定排序的Safari 15.1返回异常结果:
[[0, 1], [0, 0], [1, 1], [1, 0]]
规范要求与正确实现
根据ECMAScript规范,数组sort方法的比较器必须返回数字类型的值:
- 返回
-1:表示a应该排在b之前 - 返回
0:表示a和b的相对顺序保持不变 - 返回
1:表示b应该排在a之前
符合规范的标准比较器写法如下,在所有浏览器中都能得到正确结果:
(a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0
异常原因分析
核心差异在于不同浏览器对非规范返回值的兼容处理逻辑:
- Chrome和Firefox会自动将布尔值隐式转换为数字:
true转为1,false转为0。因此你的简写比较器在这两个浏览器中,实际等价于返回-1、1、0,刚好契合规范要求,所以能得到正确结果。 - Safari的排序引擎对比较器返回值的处理更严格,没有做布尔值到数字的隐式转换。当比较器混合返回数字和布尔值时,Safari的排序算法无法正确识别返回值的语义,导致逻辑分支错误——即使Safari支持稳定排序,这种不规范的返回值也会破坏排序逻辑,最终出现子数组逆序的异常结果。
内容的提问来源于stack exchange,提问作者o17t H1H' S'k
相关产品推荐
相关产品推荐

