首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript 陣列排序完全指南:sort() 比較函數、數值/日期/字串多型別處理與效能優化

     編輯:程式設計綜合問答

JavaScript 陣列原生 `sort()` 方法**預設按 Unicode 碼點排序字串**,直接用於數值陣列會產生錯誤順序 (如 `[1, 2, 10, 20]` → `[1, 10, 2, 20]`)。正確做法是**傳入比較函數**,並根據資料型別選擇比較邏輯。

核心語法


arr.sort((a, b) => a - b);        // 數值升序
arr.sort((a, b) => b - a);        // 數值降序
arr.sort((a, b) => a.localeCompare(b, undefined, {numeric: true})); // 字串自然排序

多型別通用排序工具函數


/**
 * 通用陣列排序
 * @param {Array} arr 目標陣列
 * @param {string|Function} key 物件屬性名或自定比較函數
 * @param {'asc'|'desc'} order 排序方向
 * @param {'number'|'date'|'string'} type 資料型別 (可選,自動推斷)
 */
function sortArray(arr, key, order = 'asc', type) {
  const direction = order === 'asc' ? 1 : -1;

  const getVal = typeof key === 'function' ? key : (item) => item[key];

  const compare = (a, b) => {
    const valA = getVal(a);
    const valB = getVal(b);

    let cmp = 0;
    const detectedType = type || detectType(valA, valB);

    switch (detectedType) {
      case 'number':
        cmp = Number(valA) - Number(valB);
        break;
      case 'date':
        cmp = new Date(valA) - new Date(valB);
        break;
      case 'string':
      default:
        cmp = String(valA).localeCompare(String(valB), undefined, {numeric: true, sensitivity: 'base'});
        break;
    }
    return direction * cmp;
  };

  return [...arr].sort(compare); // 回傳新陣列,不修改原陣列
}

function detectType(a, b) {
  if (typeof a === 'number' && typeof b === 'number') return 'number';
  if (a instanceof Date && b instanceof Date) return 'date';
  if (!isNaN(Date.parse(a)) && !isNaN(Date.parse(b))) return 'date';
  return 'string';
}

// 使用範例
const users = [
  {name: 'Alice', age: 25, join: '2023-01-15'},
  {name: 'Bob', age: 30, join: '2022-11-03'},
  {name: 'Charlie', age: 25, join: '2023-05-20'},
];

console.log(sortArray(users, 'age', 'asc', 'number'));
// [{name:'Alice',age:25,...}, {name:'Charlie',age:25,...}, {name:'Bob',age:30,...}]

console.log(sortArray(users, 'join', 'desc', 'date'));
// [{name:'Charlie',join:'2023-05-20',...}, {name:'Alice',join:'2023-01-15',...}, {name:'Bob',join:'2022-11-03',...}]

console.log(sortArray(users, 'name', 'asc'));
// 自然排序: Alice, Bob, Charlie

關鍵比較邏輯對照表

型別比較函數說明
數值(a,b) => a - b升序;降序 b - a。Number() 處理字串數字
日期(a,b) => new Date(a) - new Date(b)支援 ISO 8601、時間戳、Date 物件
字串(a,b) => a.localeCompare(b, undefined, {numeric:true})自然排序 (1, 2, 10),忽略大小寫 sensitivity:'base'
物件多欄位(a,b) => a.age - b.age || a.name.localeCompare(b.name)先按 age,相同再按 name

效能優化與避坑

  • ✅ **大陣列 (10萬+)**:考慮 **TypedArray + WebAssembly** 或 **Web Worker** 離主執行緒排序。
  • ✅ **穩定排序**:現代引擎 (V8, SpiderMonkey) `sort()` 已保證穩定 (ES2019),相等元素順序不變。
  • ❌ **不要在比較函數中做重運算** (如 `JSON.parse`、複雜正則) → 會被呼叫 O(n log n) 次。**預先轉換資料再排序**。
  • ❌ **稀疏陣列/含 undefined** → `sort()` 會將 `undefined` 排到末尾,但洞 (empty slots) 行為不一致。**先 `arr.filter(x => x != null)`**。
  • ❌ **修改原陣列副作用** → `sort()` 就地排序。函數式風格請用 `[...arr].sort(...)` 複本。

總結

JavaScript 陣列排序核心:**永遠提供比較函數**,根據型別選擇 `a-b`、`Date` 差值或 `localeCompare`。封裝通用 `sortArray` 工具函數可覆蓋 95% 業務場景,大數據量轉向 Web Worker + TypedArray 避免阻塞主執行緒。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved