在 JavaScript 中,如何以 Object 內的 properties 進行陣列排序

最近在學習 Angular 練習實作中,遇到當 Array 內的每個 element 都是一個 Obejct,但是想要根據某個條件排序這個陣列,該怎麼做?

在實作前,先參考了 Array.prototype.sort() 的說明文件
The sort() method sorts the elements of an array in place and returns the array. The default sort order is built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
這裡說明:對一個陣列的所有元素進行排序,並回傳此陣列。排序不一定是穩定的。預設的排序順序是根據字串的 Unicode 編碼位置(code points)而定。

 

可以看到上方文件中的範例,預設上是會依據字串的 Unicode 編碼位置去做排列

 

文件說明 : 指定一個函式來定義排序順序。假如省略此參數,陣列將根據各個元素轉為字串後的每一個字元之 Unicode 編碼位置值進行排序。
所以可以知道 sort() 函數會吃一個 compareFunction 作為參數,並根據compareFunction的回傳值,作為排序結果的參考。
而如果沒有放入任何 compareFunction 的實作當參數,Array 就會按照預設,根據每個字元的Unicode值進行排序
而在排序前,所有的型別將會先轉型為String才進行排序。
 

上方文件說明 : 當要運用 compareFunction 實作時
compareFunction(a, b)
要告訴 Sort() 函數如何做排序,也就是必須明確告訴它, a 跟 b 兩個 element 相比時,誰大誰小
1. 如果回傳值為小於 0,代表 a 必須要放在較小的索引值,意思是 a 會排在 b 前面。
2. 如果回傳值為 0,代表兩個值相等,則 a 與 b 皆不會改變彼此的順序。
3. 如果回傳值為大於 0,代表 a 必須放在較大的索引值,則 a 會排在 b 後面。
從上面的說明可以發現,也可以根據自行比較的結果,控制回傳值的正負,達到實現升幕集降幕的結果。
文件範例實作:

sort 方法可以直接使用函式運算式(以及閉包(closures)):

物件也可以按照其中一個屬性的值來排序
var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

// sort by name
items.sort(function(a, b) {
  var nameA = a.name.toUpperCase(); // ignore upper and lowercase
  var nameB = b.name.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }

  // names must be equal
  return 0;
});

 

所以回到練習的專案中,我們可以從建立的 Array 資料中,按照其中 level 的屬性值來做排序
data = [{
    id: 1,
    title: '第一筆資料',
    content: '測試資料1',
    date: '2019-02-28',
    status: false,
    isOpen: 'out',
    level: false
  },
  {
    id: 2,
    title: '第二筆資料',
    content: '測試資料2',
    date: '2019-02-29',
    status: false,
    isOpen: 'out',
    level: false
  },
  {
    id: 3,
    title: '第三筆資料',
    content: '測試資料3',
    date: '2019-03-05',
    status: false,
    isOpen: 'out',
    level: false
  }
  ];
讓我們在點選星星圖案時,要將該筆資料排序到最上面

所以先在 component.html 中,加入 ( click ) 事件,當觸發後執行 changeLevel () 的 function,並帶入 item 的 Array 資料

在 component.ts 中,建立 changeLevel () 的 function,並將帶入 item 中的 level 屬性值做判斷及排序

預設 level 值為 false,所以當我們觸發後,判斷當為 false 時,則改為 true,false 則一樣為 false
帶入 compareFunction(a, b) 排序,如果當點選星星時,為 true,及 a > b,回傳 -1,a 會排在 b 前面

如果當取消星星時,為 false,及 a < b,回傳 1,a 會排在 b 後面

 

 

新人發文,文章敘述如有錯誤及觀念不正確,請不吝嗇指教,感謝~
 
參考文件 :

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort