如果须要按特定程序对对象数组进行排序,咱们很有可能会间接找个 JS 库来用。其实大可不必,JS 原生中的 Array.sort就能间接一些简单又丑陋的排序。
本文中,将介绍一些 Array.sort 的惯例排序和一些骚操作。
根本数组排序
默认状况下,Array.sort函数将数组中须要排序的每个元素转换为字符串,并按 Unicode 程序对其进行比拟。
const foo = [9, 1, 4, 'zebroid', 'afterdeck'];foo.sort(); // returns [ 1, 4, 9, 'afterdeck', 'zebroid' ]const bar = [5, 18, 32, new Set, { user: 'Eleanor Roosevelt' }];bar.sort(); // returns [ 18, 32, 5, { user: 'Eleanor Roosevelt' }, Set {} ]
你可能会好奇为啥32排在5之前。 产生这种状况是因为数组中的每个元素都首先转换为字符串,并且依照Unicode程序,"32"在"5"之前。
须要留神的是,Array.sort会更改原数组。
const baz = ['My cat ate my homework', 37, 9, 5, 17];baz.sort(); // baz数组被批改console.log(baz); // shows [ 17, 37, 5, 9, 'My cat ate my homework' ]
为防止这种状况,咱们能够创立要排序的数组的新实例,而后在新的数组上进行批改。 这里能够应用 Array.slice它返回是一个新的数组实例。
// 创立baz数组的新实例并对其进行排序const sortedBaz = baz.slice().sort();
咱们还能够应用 ES6 中的开展运算符来做:
const sortedBaz = [...baz].sort();
在两种状况下,输入是雷同的:
console.log(baz); // ['My cat ate my homework', 37, 9, 5, 17];console.log(sortedBaz); // [ 17, 37, 5, 9, 'My cat ate my homework' ]
独自应用Array.sort不能对对象数组进行排序。但不用放心,sort 的还提供一个参数,该参数使数组元素依据compare函数的返回值进行排序。
应用比拟函数进行排序
假如foo和bar是compare函数要比拟的两个元素,compare函数的返回值设置如下:
小于0:foo在bar之前
大于0 :bar在foo之前
等于0:foo和bar彼此放弃不变。
来看一个简略的示例:
const nums = [79, 48, 12, 4];function compare(a, b) { if (a > b) return 1; if (b > a) return -1; return 0;}nums.sort(compare);// => 4, 12, 48, 79
咱们能够略微重构一下:
function compare(a, b) { return a - b;}
应用在应用箭头函数进行重构:
nums.sort((a, b) => a - b);
如何对对象数组进行排序
当初,咱们来按一下对对象数组的排序。假如有上面的 singers 数组:
const singers = [ { name: 'Steven Tyler', band: 'Aerosmith', born: 1948 }, { name: 'Karen Carpenter', band: 'The Carpenters', born: 1950 }, { name: 'Kurt Cobain', band: 'Nirvana', born: 1967 }, { name: 'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 },];
咱们能够应用 compare函数,而后依据 singers 中的 band 字段来进行排序。
function compare(a, b) { // 应用 toUpperCase() 疏忽字符大小写 const bandA = a.band.toUpperCase(); const bandB = b.band.toUpperCase(); let comparison = 0; if (bandA > bandB) { comparison = 1; } else if (bandA < bandB) { comparison = -1; } return comparison;}singers.sort(compare);/* returns [ { name: 'Steven Tyler', band: 'Aerosmith', born: 1948 }, { name: 'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 }, { name: 'Kurt Cobain', band: 'Nirvana', born: 1967 }, { name: 'Karen Carpenter', band: 'The Carpenters', born: 1950 }] */
如果要让下面的程序相同,能够这么做:
function compare(a, b) { ... // 乘以-1来反转返回值 return comparison * -1;}
创立一个动静排序函数
最初,排序函数更具动态性。
咱们创立一个排序函数,能够应用该函数对一组对象进行排序,这些对象的值能够是字符串或数字。 该函数有两个参数-咱们要排序的键和返回后果的程序(即升序或降序):
const singers = [ { name: 'Steven Tyler', band: 'Aerosmith', born: 1948 }, { name: 'Karen Carpenter', band: 'The Carpenters', born: 1950 }, { name: 'Kurt Cobain', band: 'Nirvana', born: 1967 }, { name: 'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 },];function compareValues(key, order = 'asc') { return function innerSort(a, b) { if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) { // 该属性在任何一个对象上都不存在 return 0; } const varA = (typeof a[key] === 'string') ? a[key].toUpperCase() : a[key]; const varB = (typeof b[key] === 'string') ? b[key].toUpperCase() : b[key]; let comparison = 0; if (varA > varB) { comparison = 1; } else if (varA < varB) { comparison = -1; } return ( (order === 'desc') ? (comparison * -1) : comparison ); };}
应用:
//数组按`band`排序,默认为升序singers.sort(compareValues('band'));// 数组按 `band` 降序排序singers.sort(compareValues('band', 'desc'));// 数组按 `name` 升序排序singers.sort(compareValues('name'));// 数 组born 降序排序singers.sort(compareValues('born', 'desc'));
在下面的代码中,hasOwnProperty办法用于查看指定的属性是否在每个对象上定义,且没有通过原型链继承。如果没有在两个对象上定义,函数返回0,排序程序放弃不变(即对象之间放弃不变)。
typeof运算符还用于查看属性值的数据类型,这使函数能够确定对数组进行排序的正确办法。 如果指定属性的值是一个字符串,则应用toUpperCase办法将其所有字符都转换为大写,因而排序时将疏忽字符大小写
最初,你能够依据本人需要来调整下面的函数。
String.prototype.localeCompare()
在下面的示例中,咱们心愿可能对对象数组进行排序,其值能够是字符串或数字。 然而,如果咱们晓得解决值是字符串的对象,则能够应用 JS 的localeCompare办法
比拟两个字符串,并返回下列值中的一个:
如果 字符串 在 字母 表中 应该 排在 字符串 参数 之前, 则 返回 一个 正数;
如果 字符串 等于 字符串 参数, 则 返回 0;
字符串 在 字母 表中 应该 排在 字符串 参数 之后, 则 返回 一个 负数;
['bjork', 'Bjork', 'Björk'].sort();// [ 'Bjork', 'Björk', 'bjork' ]['bjork', 'Bjork', 'Björk'].sort((a, b) => a.localeCompare(b));// [ 'bjork', 'Bjork', 'Björk' ]
依据compareValues函数,咱们能够这么写:
function compareValues(key, order = 'asc') { return function innerSort(a, b) { if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0; const comparison = a[key].localeCompare(b[key]); return ( (order === 'desc') ? (comparison * -1) : comparison ); };}
总结
下面就是应用一般JS 函数对对象数组排序的简短的介绍。只管许多库都提供了这种动静排序能力,但咱们本人实现这个办法其实也不信。另外,理解幕后产生了对咱们来说并没有害处。
最初
说个题外话,我在一线互联网企业工作十余年里,领导过不少同行后辈。帮忙很多人失去了学习和成长。
我意识到有很多教训和常识值得分享给大家,也能够通过咱们的能力和教训解答大家在IT学习中的很多困惑,所以在工作忙碌的状况下还是保持各种整顿和分享。
我能够将最近整顿的前端面试题收费分享进去,其中蕴含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器、数据结构与算法等等,还在继续整顿更新中,心愿大家都能找到心仪的工作。