首先,请原谅我做一次标题党;
但我觉得从发现问题到最后解决问题的过程还是蛮有意思的,特此记录一下;
背景
近两天开发的航班延误宝
是内嵌在客户端(android、ios)webview 中的 H5 页面。其中有部分内容需要前端排序后再显示。代码很简单:
let m = [6,4,8,10,3,5]
console.log('排序前:', [6,4,8,10,3,5])
m.sort((a, b) => a < b)
console.log('排序后:', m)
ps:发现这段代码的问题了么?如果你知道原因,为了节省您宝贵的时间,后面内容就不要看啦;
在 PC 浏览器中打印的内容如下:
排序前: (6) [6, 4, 8, 10, 3, 5]
排序后: (6) [10, 8, 6, 5, 4, 3]
但我用 iPhone 进行测试(只测了IOS微信浏览器、IOS航班管家客户端),却有不一样的体验:
WTF!结果和没排序一样,为甚?
解决
最开始推测可能是 sort
存在兼容问题。于是,用插入排序替代sort
进行测试,结果正常。
后来,在张(zhen)老(da)师(tui)的指导下,了解了sort
的实现规范,才明白,原来是上面的实现有问题。
哪里有问题?
在sort
实现的规范中有这么一条:若 comparefn (a,b) === 0,则有 a === b 且 b === a 。
此时我们再看var comparefn = (a, b) => a < b
,它等同于var comparefn = (a, b) => a < b ? 1 : 0
。
它有一个隐藏的漏洞:当a >= b
时,comparefn(a,b) === 0
。而根据规范,通过comparefn(a,b) === 0
可以推测出a === b
,显然这里互相矛盾。
所以,我写的这个comparefn
原本就是错误的,holyshit!
那么正确的写法应该是:var comparefn = (a, b) => b - a
。
完结撒花;
再问:为什么android和ios对此表现的不一样呢?应该是两家在具体实现上有所不同。
更多: