JS数组中sort的用法(有坑)

在 JavaScript 中,Array.prototype.sort() 方法用于对数组的元素进行排序,但它的默认行为可能和直觉不一致。以下是完整的用法解析和注意事项:


一、基本用法

1. 默认排序(⚠️ 有坑)

默认按 Unicode 编码 进行字符串排序:

const arr = [10, 2, 1, 20];
arr.sort();
console.log(arr); // [1, 10, 2, 20] ❌ 不是数值大小排序!
2. 自定义比较函数(⭐ 推荐)

通过回调函数定义排序规则:

// 数字升序排序
arr.sort((a, b) => a - b); // [1, 2, 10, 20]

// 数字降序排序
arr.sort((a, b) => b - a); // [20, 10, 2, 1]

二、排序规则详解

比较函数返回值解析:
function compare(a, b) {
  if (a < b) return -1; // a 排在 b 前面
  if (a > b) return 1;  // a 排在 b 后面
  return 0;             // 位置不变(ES6+ 后稳定排序)
}
简化写法:
// 等价于上面的 compare 函数
arr.sort((a, b) => a - b); 

三、常见场景示例

1. 对象数组排序
const users = [
  { name: 'Bob', age: 25 },
  { name: 'Alice', age: 30 }
];

// 按 age 升序
users.sort((a, b) => a.age - b.age);

// 按 name 字母排序(区分大小写)
users.sort((a, b) => a.name.localeCompare(b.name));
2. 多条件排序
const products = [
  { name: 'Laptop', price: 1000, rating: 4.5 },
  { name: 'Phone', price: 999, rating: 4.7 }
];

// 先按 rating 降序,再按 price 升序
products.sort((a, b) => {
  if (b.rating !== a.rating) return b.rating - a.rating;
  return a.price - b.price;
});
3. 字符串特殊排序
// 不区分大小写排序
const letters = ['Apple', 'banana', 'Cherry'];
letters.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));

// 含中文的排序
const names = ['张三', '李四', '王五'];
names.sort((a, b) => a.localeCompare(b, 'zh-Hans-CN'));

四、注意事项

场景问题与解决方案
修改原数组sort 是原地排序,用 [...arr].sort() 可避免改变原数组
稳定性ES2019 后 sort 稳定(相同元素保持原有顺序)
稀疏数组空位(empty)会被排序到数组末尾
非 ASCII 字符需用 localeCompare 正确处理国际化排序
无效比较函数函数未返回数字会导致意外行为(如返回布尔值)

五、实用技巧

1. 随机排序
// ⚠️ 非严格均匀随机,适用于简单场景
const arr = [1, 2, 3];
arr.sort(() => Math.random() - 0.5);
2. 按字符串长度排序
const words = ['apple', 'kiwi', 'banana'];
words.sort((a, b) => a.length - b.length); // ['kiwi', 'apple', 'banana']
3. 按日期排序
const dates = [
  '2023-10-01',
  '2023-09-15',
  '2023-12-25'
];
dates.sort((a, b) => new Date(a) - new Date(b));

六、性能对比

10,000 个数字 排序耗时测试(Chrome):

方法耗时 (ms)说明
arr.sort()1.2默认字符串排序 ❌
arr.sort((a,b)=>a-b)0.8正确数值排序 ✅
Lodash _.sortBy1.5功能更全但稍慢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值