引入
??說(shuō)明:使用語(yǔ)言為js。
??對(duì)象數(shù)組,即數(shù)組中存放的元素是一個(gè)個(gè)對(duì)象。例如
let objArr = [
{ name: "張三", sex: 'female', age: 30, birthday: "1994/10/11" },
{ name: "李四", sex: 'male', age: 20, birthday: "2001/08/11" },
{ name: "王五", sex: 'female', age: 40, birthday: "2001/01/15" }
];
??但是我們可能需要對(duì)該對(duì)數(shù)組中對(duì)象的指定屬性進(jìn)行排序,例如上述對(duì)象數(shù)組中的age,birthday。如何操作?方法之一,就是數(shù)組的sort()方法。
??下面,就一步步去分析,實(shí)現(xiàn)一份簡(jiǎn)單通用的對(duì)象數(shù)組排序方法。
實(shí)現(xiàn)對(duì)象數(shù)組排序
第一步:簡(jiǎn)單排序number屬性
??因?yàn)锳rray.sort()的“默認(rèn)排序順序是在將元素轉(zhuǎn)換為字符串,然后比較它們的UTF-16代碼單元值序列時(shí)構(gòu)建的”。好在是sort()方法接受一個(gè)用來(lái)指定按某種順序進(jìn)行排列的函數(shù)作為可選參數(shù),即arr.sort([compareFunction]),如果 compareFunction(a, b) 小于0,那么a會(huì)被排列到b之前;所以可以在此實(shí)現(xiàn)自己想要的排序方法。
注意,sort方法會(huì)改變?cè)瓟?shù)組。(sort() 方法用原地算法對(duì)數(shù)組的元素進(jìn)行排序,并返回?cái)?shù)組。)
??話不多說(shuō),直接看。
??例如上述objArr,按照age升序排序:
// 指定排序的比較函數(shù)
function compare(property) {
return function (object1, object2) {
let value1 = object1[property];
let value2 = object2[property];
// 升序
return value1 - value2;
}
}
let sortObj = objArr.sort(compare("age"));
console.log(sortObj);
??應(yīng)該會(huì)得到如下結(jié)果:

第二階段:可以排序string屬性
??但是這個(gè)寫法只能對(duì)age這個(gè)number類型的屬性其作用,如果換成name或者birthday等,就不行,因?yàn)閟tring不能直接用'-'比較得出大小。
??例如,運(yùn)行console.log('male' - 'female');,應(yīng)該會(huì)看到得出的是NaN。
??string,就應(yīng)該使用localeCompare() 方法,它返回一個(gè)數(shù)字來(lái)指示一個(gè)參考字符串是否在排序順序前面或之后或與給定字符串相同。完整語(yǔ)法:referenceStr.localeCompare(compareString[, locales[, options]])。
??所以需要簡(jiǎn)單修改一下compare()方法,修改如下:
function compare(property) {
return function (object1, object2) {
let value1 = object1[property];
let value2 = object2[property];
if (typeof (value1) == typeof (value2)) {
if (typeof (value1) === 'number') {
return value1 - value2;
}
if (typeof (value1) === 'string') {
// 升序
return value1.toString().localeCompare(value2);
}
}
}
}
let sortObj = objArr.sort(compare("birthday"));
console.log(sortObj);
??結(jié)果應(yīng)當(dāng)如下:

第三階段:可以指定升序/降序
??既然已經(jīng)到了這個(gè)程度,那可以再加一個(gè)是按照升序或者降序排列。
??簡(jiǎn)單修改如下:
function compare(property, sortType = "asc") {
return function (object1, object2) {
let value1 = object1[property];
let value2 = object2[property];
// 判斷 傳入的屬性值 是number還是 string
if (typeof (value1) == typeof (value2)) {
if (typeof (value1) === 'number') {
// 如果是升序
if (sortType === "asc") {
return value1 - value2;
} else if (sortType === "desc") {
// 如果是降序
return value2 - value1;
}
}
if (typeof (value1) === 'string') {
// 如果是升序
if (sortType === "asc") {
return value1.toString().localeCompare(value2);
} else if (sortType === "desc") {
// 如果是降序
return value2.toString().localeCompare(value1);
}
}
}
}
}
// 生日,降序
let sortObj = objArr.sort(compare("birthday", 'desc'));
console.log(sortObj);
??得到的結(jié)果應(yīng)該如下:

第四階段:封裝成通用方法
??反正都這樣了,再簡(jiǎn)單封裝一下,導(dǎo)出成一個(gè)方法,后續(xù)直接使用。
??新建一個(gè)objArraySort.js,放入以下代碼:
// sort使用的排序方法
// 傳入對(duì)象數(shù)組用于排序的對(duì)象的屬性,升序/降序
function compare(property, sortType = "asc") {
// 如果不是 asc,desc,不做下一步比較
if (!(sortType === "desc" || sortType === "asc")) {
return;
}
return function (object1, object2) {
// 取得對(duì)象屬性值
let value1 = object1[property];
let value2 = object2[property];
// 如果該對(duì)象不存在這個(gè)屬性,也不做后續(xù)比較
if (!value1 || !value2) {
return;
}
// 如果兩個(gè)屬性取得的值不是一個(gè)類型的就不用比較了
if (typeof (value1) == typeof (value2)) {
// 判斷 傳入的屬性值 是number還是 string
if (typeof (value1) === 'number') {
// 如果是升序
if (sortType === "asc") {
return value1 - value2;
} else {
// 如果是降序
return value2 - value1;
}
} else if (typeof (value1) === 'string') {
// 如果是升序
if (sortType === "asc") {
return value1.toString().localeCompare(value2);
} else {
// 如果是降序
return value2.toString().localeCompare(value1);
}
} else {
// 其它類型就不排序了
return;
}
} else {
return;
}
}
}
// 通用方法,需要傳入 需要排序的對(duì)象數(shù)組、對(duì)象屬性、排序方式
function objectArraySort(array, property, sortType) {
// 如果不是對(duì)象數(shù)組用這個(gè)方法,返回的是undefined
if (!(array instanceof Array)) {
return;
}
return array.sort(compare(property, sortType));
}
// 導(dǎo)出
module.exports = {
objectArraySort: objectArraySort,
}
??再將剛剛的objArr按照age降序排序:
// 引入模塊
const oas = require("./objectArraySort");
// 調(diào)用方法,傳入需要排序的對(duì)象數(shù)組、對(duì)象屬性、排序方式
let sortObj = oas.objectArraySort(objArr, 'age', 'desc');
console.log(sortObj);
??應(yīng)該會(huì)得到以下結(jié)果:

??至此,一個(gè)簡(jiǎn)單通用的對(duì)象數(shù)組按照其對(duì)象指定屬性排序的模塊就完成了。實(shí)踐有效,如果有問(wèn)題,可提出交流,謝謝。