做者: James Hibbard
譯者:前端小智
來源:sitepoint
點贊再看,養成習慣本文
GitHub
https://github.com/qq44924588... 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。javascript
最近開源了一個 Vue 組件,還不夠完善,歡迎你們來一塊兒完善它,也但願你們能給個 star 支持一下,謝謝各位了。前端
github 地址:https://github.com/qq449245884/vue-okr-treevue
若是須要按特定順序對對象數組進行排序,咱們頗有可能會直接找個 JS 庫來用。其實大可沒必要,JS 原生中的 Array.sort
就能直接一些複雜又漂亮的排序。java
本文中,將介紹一些 Array.sort 的常規排序和一些騷操做。git
默認狀況下,Array.sort
函數將數組中須要排序的每一個元素轉換爲字符串,並按 Unicode
順序對其進行比較。github
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
方法將其全部字符都轉換爲大寫,所以排序時將忽略字符大小寫
最後,你能夠根據本身需求來調整上面的函數。
在上面的示例中,咱們但願可以對對象數組進行排序,其值能夠是字符串或數字。 可是,若是咱們知道處理值是字符串的對象,則可使用 JS 的localeCompare
方法
比較兩個字符串,並返回下列值中的一個:
['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 函數對對象數組排序的簡短的介紹。儘管許多庫都提供了這種動態排序能力,但咱們本身實現這個方法其實也不信。另外,瞭解幕後發生了對咱們來講並無壞處。
今天就跟你們分享到這裏了,感謝你們的觀看,咱們下期再見。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
原文:https://www.sitepoint.com/sor...
文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。