总结在前端排序中遇到的问题总结在前端排序中遇到的问题
貌似前端圈一直以来流传着一种误解:前端用不到算法知识。长久以来,大家或许都曾受这种说法的影响。直到前阵子遇到一
个产品需求,回过头来看,发现事实并非如此。
前端排序前端排序
前端排序的场景前端排序的场景
前端将排序条件作为请求参数传递给后端,后端将排序结果作为请求响应返回前端,这是一种常见设计。但是对于有些产品则
不是那么适用。
试想一个场景:你在使用美食类APP时,是否会经常切换排序方式,一会儿按照价格排序,一会儿按照评分排序。
实际生产中,受限于服务器成本等因素,当单次数据查询成为整体性能瓶颈时,也会考虑通过将排序在前端完成的方式来优化
性能。
排序算法排序算法
感觉这个没什么介绍的必要,作为计算机科学的一种基础算法,描述就直接照搬 Wikipedia。
这里存在这一段内容纯粹是为了承(cou)上(man)启(zi)下(shu)。
JavaScript的排序的排序
既然说到前端排序,自然首先会想到JavaScript的原生接口 Array.prototype.sort。
这个接口自 ECMAScript 1st Edition 起就存在。让我们看看最新的规范中关于它的描述是什么样的。
Array.prototype.sort规范规范
Array.prototype.sort(compareFn)
代码如下:
The elements of this array are sorted. The sort is not necessarily stable (that is, elements that compare equal do not
necessarily remain in their original order). If comparefn is not undefined, it should be a function that accepts two arguments x
and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.
显然,规范并没有限定 sort 内部实现的排序算法是什么。甚至接口的实现都不需要是 稳定排序稳定排序 的。这一点很关键,接下来会
多次涉及。
在这样的背景下,前端排序这件事其实取决于各家浏览器的具体实现。那么,当今主流的浏览器关于排序是怎么实现的呢?接
下来,我们分别简单对比一下 Chrome、Firefox 和 Microsoft Edge。
Chrome中的实现中的实现
Chrome 的JavaScript引擎是 v8。由于它是开源的,所以可以直接看源代码。
整个 array.js 都是用 JavaScript 语言实现的。排序方法部分很明显比曾经看到过的快速排序要复杂得多,但显然核心算法还是
快速排序。算法复杂的原因在于 v8 出于性能考虑进行了很多优化。(接下来会展开说)
Firefox中的实现中的实现
暂时无法确定Firefox的JavaScript引擎即将使用的数组排序算法会是什么。[3]
按照现有的信息,SpiderMoney 内部实现了 归并排序。
Microsoft Edge中的实现中的实现
Microsoft Edge 的JavaScript引擎 Chakra 的核心部分代码已经于2016年初在Github开源。
通过看源代码可以发现,Chakra 的数组排序算法实现的也是 快速排序。而且相比较于 v8,它就只是实现了纯粹的快速排
序,完全没有 v8 中的那些性能优化的踪影。
JavaScript数组排序的问题数组排序的问题
众所周知,快速排序 是一种不稳定的排序算法,而 归并排序 是一种稳定的排序算法。由于不同引擎在算法选择上的差异,导
致前端依赖 Array.prototype.sort 接口实现的JavaScript代码,在浏览器中实际执行的排序效果是不一致的。
排序稳定性的差异需要有特定的场景触发才会存在问题;在很多情况下,不稳定的排序也不会造成影响。
假如实际项目开发中,对于数组的排序没有稳定性的需求,那么其实看到这里为止即可,浏览器之间的实现差异不那么重要。