假设我们有这样一个数组a
var a = [{b:1},{b:15},{b:8},{b:9},{b:17},{b:94},{b:11},{b:8},{b:23},{b:77},{b:undefined},{b:3},{b:4},{b:2},{b:16}]
参照MDN的文档,如果我对这个数组进行sort升序排序,那么含有b的值为undefined的那个对象将会被排序到最后一位去:
a.sort((object1,object2) => object1.b - object2.b)
然而以上代码的执行结果却是
[{"b":1},{"b":16},{"b":8},{"b":9},{"b":17},{"b":94},{"b":11},{"b":15},{"b":23},{"b":77},{"b":undefined},{"b":3},{"b":4},{"b":2},{"b":8}]
显然含有b为undefined的对象没有排序到最后一位。并且数组也没有升序排列。
但是如果我先把所有的b用map给筛选出来再进行升序排序,像下面这样:
a.map(object => object.b).sort((a,b) => a-b)
[1, 2, 3, 4, 8, 8, 9, 11, 15, 16, 17, 23, 77, 94, undefined]
显然,数组被正确排序并且undefined处在最后一位。
结论:在含有undefined属性的数组用sort方法进行排序的时候,如果数字里面的undefined值不是处于直接引用状态的话,那么sort排序将会失效(出来的数组是乱序的)。
sort 函数之加深理解
对于数组排序来说,一般来说只想要两个结果——升序或者降序。然而对于乱序的数组来说,升序和降序采取了两种完全不同策略。对于升序来说,假定我选定数组中任意两个相邻值a和b。在不知道a,b具体的值得情况下采取如下策略:
如果a大于b,那么交换a和b的位置。如果a小于b,则不用交换a和b的位置。同理,降序的策略如下:如果a小于b,那么交换a和b的位置。如果a大于b,则不用交换a和b的位置。
如果把这个策略看做一个函数的话,函数的值决定是否交换位置。这里假如我们规定函数的值为-1或者0的话
则a,b的位置不用交换。如果函数的值为1的话,则交换a和b的位置
所以写出升序,降序函数如下:
function 升序(a,b){
if(a < b){
return -1 // 升序策略下,如果a小于b,则不做交换
}else{
return 1 // 升序策略下,如果a大于b,则交换a,b位置
}
}
function 降序(a,b){
if(a < b){
return 1 // 降序策略下,如果a小于b,则交换a,b位置
}else{
return -1 // 升序策略下,如果a大于b,则不做交换
}
}
对升序和降序的简化
上面的升序和降序函数可以简化成以下函数
function 升序(a,b){
return a-b // 如果a小于b 则返回负数,不做交换。 如果a大于b 返回正数,交换a,b位置
}
function 降序(a,b){
return a-b // 如果a大于b 则返回负数,不做交换。 如果a小于b 返回正数,交换a,b位置
}