JavaScript 中 Array.sort 函数的疑问?

image.png
今天在初次使用 sort 函数的时候,遇到了一个疑问,在这里我传入的回调函数中,我打印了 a,b 。

控制台的输出结果为。
image.png

我了解到,sort 会改变原数组的顺序。下面为遇到的问题

问题1: sort 会边改变顺序,边比较吗?还是会再完全比较结束的时候,调整数组顺序?

问题2: 上面控制台的结果,当我第一次打印的时候,为什么此时的 a 为 1,b 为 3 呢?这时候排序不是还没开始吗?a,和 b 不是应该分别对应数组的 第一项和第二项吗? 我理解的应该是 a 应该为3 而 b 应该 为 1才对啊?🤔

还望各位不吝赐教

阅读 2k
3 个回答

问题1: sort()函数的工作原理是在对数组元素进行比较时,依据比较函数的返回值来决定元素的新顺序。整个过程中,它会边比较边调整数组的顺序,直到整个数组按照比较函数所定义的顺序排列完成。

问题2: 关于控制台输出的结果,JavaScript 的Array.prototype.sort()函数默认情况下将数组元素转换为字符串并按照字符的 Unicode 码点进行排序。但是,当我们提供自定义的比较函数时(如(a, b) => a - b),sort()函数会根据此函数对元素进行排序。

此外,Array.prototype.sort()函数的具体实现方式因 JavaScript 引擎而异。因此,不同的浏览器或 JavaScript 环境可能在执行sort()函数时采用不同的排序算法,如快速排序、插入排序等。这意味着,不同环境下,比较函数的调用顺序可能会有所不同。在您的示例中,控制台输出的结果可能是因为在排序算法的特定实现中,比较函数首次调用时选择了数组中的第二个和第一个元素作为ab

总之,不能确保 sort() 函数会按照特定的顺序对数组进行比较,因为这取决于 JavaScript 引擎实现的排序算法。

问题 1:取决于当前执行 js 脚本的引擎的排序算法,排序算法有很多,最常见的比如冒泡和快排,还有类似插入排序、堆排序之类的,不同的算法在算法复杂度和空间复杂度上不一样,所以不能一概而论。

据我所知,大部分引擎都是使用的快速排序的算法,另外在数组比较短(好像是长度小于 10 的时候)的时候,会用插入排序,因为这种情况快排没有压倒性的优势。

问题 2:其实我觉得你在明白问题 1 的基础上,第二个问题也应该能明白为什么了。

如果我们要自己来实现一个 Array.prototype.sort 方法,不论使用排序算法,最关键的部分都是如何判定两个元素之间的大小关系,因此,对于这个回调函数来讲,它的参数与排序算法之间,是依赖注入的关系,换句话说,就是回调函数完全不需要关心传入的参数的具体含义是什么,它只需要关系如何决定这两个参数的大小关系就行了。

回到你的问题,你的问题是关于 a 和 b 的含义以及它们的行为到底是怎样的,这个问题本身就没什么意义,如果硬要回答,就是问题 1 中所说的,具体情况具体分析,但对于 Array.prototype.sort 这种声明式的排序方法来讲,完全没有必要关心这些。

我记得社区之前有人分析过 Array.sort() 方法的原理,你可以看看,但是各个浏览器之间的实现方式是有区别的。
JS 中 Array.sort 的那些事儿
Array.prototype.sort()方法到底是如何排序的?
[笔记] 深入理解 JavaScript Array.sort()

以及相关的讨论:
js中sort函数的底层实现机制?

只不过这些都是比较早期的了,后面我记得有一篇文章又重新讨论过 sort() 方法的实现,好像是 Chromium 又调整了排序方法。

或者如果有闲有时间的话,可以直接看 V8的源码部分

推荐问题
宣传栏