一、问题的起因
偶然发现,在某些浏览器中显示的图表,日期排序混乱,如下图。
逐步排查原因:
1、接口返回的数据没有问题
2、大部分浏览器显示没有问题,只有Chrome浏览器有问题
3、新版本的Chrome浏览器没有问题,出现问题的浏览器版本在70以下
二、真相只有一个
考虑到谷歌浏览器在70版本后,对sort方法进行了调整,遂定位到问题的原因为sort排序的问题。为了更直观的感受到不同版本浏览器中排序结果区别,在控制台中同时执行了以下排序操作。
var a = [10,5,40,25,1000,1];
a.sort(function(){
return -1;
});
根据sort方法的定义,以上代码是将a数组倒序显示。在72.0版本中,执行结果如下
跟预期结果一致,没有问题。然而在69.0版本中结果却完全相反。
三、我的猜想
看到这个结果,我想知道Chrome V8引擎,在进行排序算法时,究竟做了什么。
使用Chrome版本 73.0.3683.86(正式版本)(64 位)来验证,首先在控制台中对一个数组进行升序排序。
var array = [4, 2, 5, 3, 1];
function compare(a, b) {
console.log(a,b);
return a - b;
}
array.sort(compare);
输出结果
第一行输出2 4,2-4<0,2移到4前面,数组为[2,4,5,3,1]
第二行输出5 2,5-2>0,数组不变
第三行输出5 4,5-4>0,数组不变
根据前三行的输出规律,接下来输出依次应该是3 2,3 4,3 5,然而第四行却直接输出了3 4,这是因为算法使用了二分法,提高比较效率,3-4<0,3移到4前面,数组为[2,3,4,5,1]。
由于3<4,所以第五行直接比较3 2,3-2>0,数组不变
第六行,依旧按照二分法,从1 4,开始比较,1-4<0,1移到4前面,数组为[2,3,1,4,5]
同理,第七行结果为[2,1,3,4,5],第八行结果为[1,2,3,4,5],排序完毕。
四、验证猜想
为了验证上面推理的正确性,换一个数组验证一遍,结果如下
第一行,5-10<0,5移到10前面,结果[5,10,40,25,1000,1]
第二行,40-5>0,数组不变
第三行,40-10>0,数组不变
第四行,采用二分法,直接比较25 10,25-10>0,数组不变
第五行,由于25大于10,所以比较25 40,25-40<0,25移到40前面,结果[5,10,25,40,1000,1]
第六行,采用二分法,比较1000 25,1000-25>0,数组不变
第七行,由于1000大于25,所以比较1000 40,1000-40>0,数组不变
第八行,采用二分法,比较1 25,1-25<0,1移到25前面,结果[5,10,1,25,40,1000]
第九行,由于1<25,所以比较1 10,1-10<0,1移到10前面,结果[5,1,10,25,40,1000]
第十行,同理,结果为[1,5,10,25,40,1000],排序结束。与上述推理结果完全一致。
五、猜想的延伸
当排序的数组很长的时候,每一次比较都会是一次二分,我后续使用长数组验证过了,由于数组太长,这里就不一行行来验证了。若有错误和其他更好的猜想,欢迎指正和提出。