sort()当中可以传入一个“判断准则”(sortBy)函数,用以定义比较元素时按照什么样的规则。
一、当不传入 sortBy 时使用
如果sort 不传参数,则按照默认规则排序。即直接先把数组中的元素转为字符串格式,然后先按照字符顺序逐个比较 ascii 码值并排序。
var arr = [3,2,6,16,7,18,25];
arr = arr.sort();
console.log(arr); //[16, 18, 2, 25, 3, 6, 7]
有趣的是,如果 arr 中既有对象,又有数组进行排队的话,结果总是会先把数组排在前面,对象排在后面,且数组依然会按照上述步骤进行排序,而对象则不进行排序。
进而笔者汇总了各种类型的数据进行默认排序,效果如下:
var arr = [
{ a: "zh" }, NaN, { k: "abc" }, [], {}, undefined, null,
NaN, null, [13, 4, 7], [], [13, 4, 3], { b: "zbc" }
];
arr = arr.sort();
console.log(arr);
///////////////////////////////////////////
0: []
1: []
2: (3) [13, 4, 3]
3: (3) [13, 4, 7]
4: NaN
5: NaN
6: {k: "abc"}
7: {a: "zh"}
8: {}
9: {b: "zbc"}
10: null
11: null
12: undefined
结果你可以看到,null,undefined会按照 null 在前,undefined 在后的顺序排在最后面,而 NaN 则会排在 [array] 和 {object} 之间,[] 会排在数组最前面,[array]会按照默认规则排序,而 {} 不排序。
二、当传入 sortBy 时使用
传入一个 sortBy 函数可以帮助你定义整个数组里面量元素之间的排序规则,且 sortBy 函数的返回值对除 正数 和 true 以外的任何其他值都不敏感。你可以尝试使得 sortby 函数的返回值为0、负数、null、undefined、NaN、[]、{}、或其他任意类型,其结果都是不排序,即原封不动地按原顺序返回。
正是因为有了 sortby 函数,使得你可以对对象数组中,按照特定属性的值进行比较排序。
相信你在网络上搜索到过关于 sort 的升降序用法。这里不再举例讨论,笔者带你深入探索 sort 的运作过程和机制。
var kk = 1;
var arr = [94, 4, 48, 68, 15, 42, 44, 32, 50, 80];
function sortby(a, b) {
console.log("这是第" + kk + "次比较,本次比较" + a + "和" + b);
kk++;
return a - b;
}
arr.sort(sortby);
console.log(arr);
////////////////////////////////////////////////////////
这是第1次比较,本次比较94和4
这是第2次比较,本次比较94和48
这是第3次比较,本次比较4和48
这是第4次比较,本次比较94和68
这是第5次比较,本次比较48和68
这是第6次比较,本次比较94和15
这是第7次比较,本次比较68和15
这是第8次比较,本次比较48和15
这是第9次比较,本次比较4和15
这是第10次比较,本次比较94和42
这是第11次比较,本次比较68和42
这是第12次比较,本次比较48和42
这是第13次比较,本次比较15和42
这是第14次比较,本次比较94和44
这是第15次比较,本次比较68和44
这是第16次比较,本次比较48和44
这是第17次比较,本次比较42和44
这是第18次比较,本次比较94和32
这是第19次比较,本次比较68和32
这是第20次比较,本次比较48和32
这是第21次比较,本次比较44和32
这是第22次比较,本次比较42和32
这是第23次比较,本次比较15和32
这是第24次比较,本次比较94和50
这是第25次比较,本次比较68和50
这是第26次比较,本次比较48和50
这是第27次比较,本次比较94和80
这是第28次比较,本次比较68和80
这里 sortby 接受的两个参数 a, b 是按原数组顺序的要进行比较的两个相邻元素
【结论】: sort 函数的排序是一个冒泡过程,以此实现每两个相邻元素之间都能做到一次比较的目的。在传入 sortby 后定义该比较规则并覆盖默认比较规则,每两个相邻元素进行 sortby 函数规则比较。直到再也没有符合条件(返回正数或true)的两相邻元素为止。
对于 sort 操作之后的返回值,是一个对原数组的浅拷贝。并且直接对原数组进行修改,无需再次赋值。
【引申】:这里可以运用其工作机制这样定义 sortby
var kk = 1;
var arr = [45, 13, 92, 62, 18, 80, 63, 82, 54, 72];
functionn sortby(a, b){
console.log("这是第" + kk + "次比较,本次比较" + a + "和" + b);
kk++;
return 1;
}
arr = arr.sort(sortby);
console.log(arr);
//////////////////////////////////////////////////////////////////
这是第1次比较,本次比较45和13
这是第2次比较,本次比较45和92
这是第3次比较,本次比较13和92
这是第4次比较,本次比较45和62
这是第5次比较,本次比较13和62
这是第6次比较,本次比较92和62
这是第7次比较,本次比较45和18
这是第8次比较,本次比较13和18
这是第9次比较,本次比较92和18
这是第10次比较,本次比较62和18
这是第11次比较,本次比较45和80
这是第12次比较,本次比较13和80
这是第13次比较,本次比较92和80
这是第14次比较,本次比较62和80
这是第15次比较,本次比较18和80
这是第16次比较,本次比较45和63
这是第17次比较,本次比较13和63
这是第18次比较,本次比较92和63
这是第19次比较,本次比较62和63
这是第20次比较,本次比较18和63
这是第21次比较,本次比较80和63
这是第22次比较,本次比较45和82
这是第23次比较,本次比较13和82
这是第24次比较,本次比较92和82
这是第25次比较,本次比较62和82
这是第26次比较,本次比较18和82
这是第27次比较,本次比较80和82
这是第28次比较,本次比较63和82
这是第29次比较,本次比较45和54
这是第30次比较,本次比较13和54
这是第31次比较,本次比较92和54
这是第32次比较,本次比较62和54
这是第33次比较,本次比较18和54
这是第34次比较,本次比较80和54
这是第35次比较,本次比较63和54
这是第36次比较,本次比较82和54
这是第37次比较,本次比较45和72
这是第38次比较,本次比较13和72
这是第39次比较,本次比较92和72
这是第40次比较,本次比较62和72
这是第41次比较,本次比较18和72
这是第42次比较,本次比较80和72
这是第43次比较,本次比较63和72
这是第44次比较,本次比较82和72
这是第45次比较,本次比较54和72
[72, 54, 82, 63, 80, 18, 62, 92, 13, 45]
所以你可以看到,每一次对于返回正数都会促使两数进行位置交换,最终得到一个倒序结果。
但是由于效率低下,而且经实验证明有几率引入不良bug,所以此功能只做了解参考,若要倒序效果请直接使用 reverse() 。
/////////////////////////////////////////////////////
本文乃私人学习笔记,若有错误之处还望请指正。
/////////////////////////////////////////////////////
网友评论