本文详细解析JavaScript中数组sort方法的默认行为与自定义排序逻辑。通过对比默认按位排序与传入回调函数的区别,深入探讨比较函数返回值(正数、负数、零)对元素位置的影响。文章通过分类讨论a与b的大小关系,阐明为何return a-b可实现升序,而return b-a实现降序,并提供了显式判断的替代写法以供参考。
sort 方法的默认排序行为
在简单使用 sort 方法时,其默认行为是按字符编码值进行排序。例如:
var arr = [1, 22, 15, 32, 4, 5]
arr.sort()//[1,15,22,32,4,5]自定义排序回调函数
这种结果通常无法满足实际开发中的数值排序需求。因此,我们可以在调用 sort 方法时传入一个比较函数(回调函数),以此自定义排序规则。下面展示了两种排序结果:分别是升序排序和降序排序。
var arr = [1, 22, 15, 32, 4, 5]
arr.sort((a, b) => {return a - b}) // 升序排序 [1, 4, 5, 15, 22, 32]
arr.sort((a, b) => {return b - a}) // 降序排序 [32, 22, 15, 5, 4, 1]回调函数的标准格式为 (a, b) => { return xxx },其中 a 和 b 代表数组中参与比较的任意两个元素。
当回调函数的返回值大于 0 时,元素 a 会被放置在元素 b 的后面;
当返回值小于 0 时,元素 a 会被放置在元素 b 的前面;
当返回值等于 0 时,元素 a 和 b 的相对位置保持不变。
排序原理与分类讨论
那么,为什么返回 a - b 就能实现升序,而返回 b - a 就能实现降序呢?
我们可以通过类似高中数学中的分类讨论法来简单分析。
当 a > b 时,
a - b > 0,根据排序规则,a 排在 b 后面,结果为 b, a(符合升序);
b - a < 0,根据排序规则,a 排在 b 前面,结果为 a, b(符合降序)。
当 b > a 时,
a - b < 0,根据排序规则,a 排在 b 前面,结果为 a, b(符合升序);
b - a > 0,根据排序规则,a 排在 b 后面,结果为 b, a(符合降序)。
当 a = b 时,
a - b = 0 且 b - a = 0,根据排序规则,a 和 b 的位置保持不变。
综上所述,
无论 a 大于 b 还是 b 大于 a,return a - b 总能保证较小的数排在前面,从而得到升序结果;而 return b - a 总能保证较大的数排在前面,从而得到降序结果。
显式判断的替代写法
此外,return a - b 或 return b - a 只是基于上述逻辑的简便写法。
如果难以理解这种简写,完全可以采用显式的条件判断方式,如下所示同样可以实现升序排序:
因为返回值大于0,把a放在后面,所以a大于b时候,返回一个正数。后面理解同理。
var arr = [1, 22, 15, 32, 4, 5]
arr.sort((a, b) => {
if (a > b) return 1;
else if (a < b) return -1;
else return 0;
}); // [1,4,5,15,22,32]