我们都知道sort()接收一个比较函数作为排序的依据,例如:
升序
function sortNumber(a,b)
{
return a - b
}
降序
function sortNumber(a,b)
{
return b - a
}
但是你知道为什么返回两个不一样的表达式就可以实现升序、降序吗?
我们看到的解释基本都是下面这样,比如w3school上的解释:
- 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
- 若 a 等于 b,则返回 0。
- 若 a 大于 b,则返回一个大于 0 的值。
这是什么鬼,你可能会跟我刚看到这个一样迷惑。。。
下面我就谈谈我自己的理解:
首先要明白这个:
sort() 的返回值
对数组的引用。请注意,数组在原数组上进行排序,不生成副本。
比较函数返回一个大于0的数,那这两个数组元素就需要换位,这样经过循环比较,最终返回一个升序的数组;
比较函数返回一个小于0的数,那这两个数组元素就不需要换位,这样经过循环比较,最终返回一个降序的数组。
直接码代码:
let arr = [11,1,5,99,3]
let g = 1
function compare (a ,b) {
console.log(`上次操作后的数组是 ${arr} ------ 第${g}次循环 a = ${a} , b = ${b} `)
g++
return a - b
}
arr.sort(compare)
console.log(`最后的数组是 ${arr}`)
这段代码输出是这样的:
上次操作后的数组是 11,1,5,99,3 ------ 第1次循环 a = 11 , b = 1
上次操作后的数组是 1,11,5,99,3 ------ 第2次循环 a = 11 , b = 5
上次操作后的数组是 1,11,11,99,3 ------ 第3次循环 a = 1 , b = 5
上次操作后的数组是 1,5,11,99,3 ------ 第4次循环 a = 11 , b = 99
上次操作后的数组是 1,5,11,99,3 ------ 第5次循环 a = 99 , b = 3
上次操作后的数组是 1,5,11,99,99 ------ 第6次循环 a = 11 , b = 3
上次操作后的数组是 1,5,11,11,99 ------ 第7次循环 a = 5 , b = 3
上次操作后的数组是 1,5,5,11,99 ------ 第8次循环 a = 1 , b = 3
最后的数组是 1,3,5,11,99
结论
sort()排序是一个循环比较前后两个数值的过程,并在每次循环后改变原来数组;
每次比较返回的值只能用于决策这次比较的两个数组是否需要更换位置;
如果比较这两个数值后返回的值大于0,则两个数组元素换位置(说白了就是小的在前,大的在后,升序);
小于0,这不换位置(大的在前,小的在后,降序)。
你可以试下打印出降序的过程看看。
最后提供一个对象数组排序的方法:
const arr = [
{name:'小明',age:12},
{name:'小刚',age:13},
{name:'小红',age:11}
]
function compare(prop){
return function(a,b){
const value1 = a[prop];
const value2 = b[prop];
return value1 - value2
}
}
arr.sort(compare('age'))
//排序后
arr = [
{name:'小红',age:11}
{name:'小明',age:12},
{name:'小刚',age:13},
]