news 2026/5/3 7:39:17

JavaScript 原生 sort() 方法详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript 原生 sort() 方法详解

JavaScript 原生sort()方法详解

一、基本语法

javascript

// 语法 arr.sort([compareFunction]) // 返回值:排序后的原数组(原地修改) const sortedArray = arr.sort(compareFunction);

二、默认行为(不使用比较函数)

1.字符串排序(默认)

javascript

const fruits = ['banana', 'apple', 'cherry', 'date']; fruits.sort(); console.log(fruits); // ['apple', 'banana', 'cherry', 'date'] const numbersAsStrings = ['10', '2', '1', '20']; numbersAsStrings.sort(); console.log(numbersAsStrings); // ['1', '10', '2', '20'] ⚠️ 按字符串排序

2.数字排序问题

javascript

const numbers = [10, 2, 1, 20]; numbers.sort(); console.log(numbers); // [1, 10, 2, 20] ❌ 不是数字顺序! // 这是因为 sort() 默认将元素转换为字符串比较 // 比较过程:"10" < "2" // true(按字典序比较)

三、比较函数详解

1.基本数字排序

javascript

// 升序排序 arr.sort((a, b) => a - b); // 降序排序 arr.sort((a, b) => b - a); // 完整示例 const numbers = [40, 100, 1, 5, 25, 10]; numbers.sort((a, b) => a - b); console.log(numbers); // [1, 5, 10, 25, 40, 100] numbers.sort((a, b) => b - a); console.log(numbers); // [100, 40, 25, 10, 5, 1]

2.比较函数工作原理

javascript

// 比较函数应该返回: // - 负数:a 排在 b 前面 // - 零:a 和 b 相对位置不变 // - 正数:a 排在 b 后面 function compare(a, b) { if (a < b) { return -1; // a 在前 } if (a > b) { return 1; // a 在后 } return 0; // 位置不变 } // 简化版(仅适用于数字) function compareNumbers(a, b) { return a - b; // 升序 }

四、V8 引擎实现原理

1.使用的算法:Timsort

javascript

// Timsort = Tim Peters' sort = 归并排序 + 插入排序优化 // 特点: // 1. 稳定排序(相等元素保持原顺序) // 2. 自适应(根据数据特征选择策略) // 3. 时间复杂度:O(n log n) // 4. 空间复杂度:O(n) // 工作原理: // 1. 寻找"run"(已经有序的片段) // 2. 小片段使用插入排序 // 3. 使用归并排序合并片段 // 4. 优化内存使用(原地归并或临时数组)

2.性能特征

javascript

// 不同数据规模的性能表现 const dataSizes = [100, 1000, 10000, 100000, 1000000]; // Timsort 对以下情况特别优化: // 1. 部分有序数组 // 2. 包含重复元素的数组 // 3. 逆序数组 // 4. 随机数组 // 在 Chrome 中的实际表现: // - 小数组(< 10):插入排序 // - 中等数组:快速排序变体 // - 大数组:Timsort

五、复杂对象排序

1.按对象属性排序

javascript

const users = [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 35 } ]; // 按年龄升序 users.sort((a, b) => a.age - b.age); // 按名字字母顺序 users.sort((a, b) => a.name.localeCompare(b.name)); // 多条件排序 users.sort((a, b) => { if (a.age !== b.age) { return a.age - b.age; // 先按年龄 } return a.name.localeCompare(b.name); // 年龄相同按名字 });

2.自定义排序规则

javascript

const priorities = ['high', 'medium', 'low']; const tasks = [ { title: 'Task A', priority: 'medium' }, { title: 'Task B', priority: 'high' }, { title: 'Task C', priority: 'low' } ]; tasks.sort((a, b) => { return priorities.indexOf(a.priority) - priorities.indexOf(b.priority); }); // 结果:high -> medium -> low

六、特殊排序需求

1.中文排序

javascript

const chineseNames = ['张三', '李四', '王五', '赵六']; // 简单排序(Unicode顺序) chineseNames.sort(); console.log(chineseNames); // Unicode 顺序 // 正确的中文拼音排序 chineseNames.sort((a, b) => a.localeCompare(b, 'zh-CN')); console.log(chineseNames); // 按拼音排序 // 支持更多选项 chineseNames.sort((a, b) => a.localeCompare(b, 'zh-CN', { sensitivity: 'base', // 忽略大小写和重音 numeric: true // 数字作为数字比较 }) );

2.带单位的字符串排序

javascript

const sizes = ['10px', '2px', '100px', '50px']; sizes.sort((a, b) => { const numA = parseInt(a); const numB = parseInt(b); return numA - numB; }); console.log(sizes); // ['2px', '10px', '50px', '100px']

3.日期排序

javascript

const dates = [ '2024-01-15', '2023-12-01', '2024-02-20', '2023-11-10' ]; dates.sort((a, b) => new Date(a) - new Date(b)); // 或 dates.sort((a, b) => a.localeCompare(b)); // 字符串比较也适用

七、性能优化技巧

1.缓存比较结果

javascript

// 优化前(每次比较都计算) const complexObjects = [...]; // 大量复杂对象 complexObjects.sort((a, b) => calculateComplexValue(a) - calculateComplexValue(b) ); // 优化后(Schwartzian transform) complexObjects .map(obj => ({ original: obj, value: calculateComplexValue(obj) })) .sort((a, b) => a.value - b.value) .map(item => item.original);

2.避免在比较函数中创建对象

javascript

// 不好:每次比较都创建新对象 arr.sort((a, b) => { const dateA = new Date(a.timestamp); const dateB = new Date(b.timestamp); return dateA - dateB; }); // 好:预先处理 arr.forEach(item => { item._sortDate = new Date(item.timestamp); }); arr.sort((a, b) => a._sortDate - b._sortDate); arr.forEach(item => delete item._sortDate);

八、常见陷阱

1.原地修改问题

javascript

const original = [3, 1, 4, 1, 5]; const sorted = original.sort(); console.log(original); // [1, 1, 3, 4, 5] ❌ 原数组被修改了! console.log(sorted); // [1, 1, 3, 4, 5] 同一个数组 // 正确做法:先复制 const safeSorted = [...original].sort(); // 或 const safeSorted = original.slice().sort();

2.不稳定的比较函数

javascript

// 错误的比较函数(可能引起问题) [1, 2, 3, 4, 5].sort(() => Math.random() - 0.5); // 这不保证均匀分布,也不高效 // 正确洗牌算法(Fisher-Yates) function shuffle(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; }

3.NaN 处理

javascript

const arr = [1, NaN, 3, 2, NaN, 4]; arr.sort((a, b) => a - b); console.log(arr); // [1, 2, 3, 4, NaN, NaN] // NaN 被排到最后 // 自定义 NaN 处理 arr.sort((a, b) => { if (isNaN(a) && isNaN(b)) return 0; if (isNaN(a)) return 1; // NaN 在后 if (isNaN(b)) return -1; // 非NaN在前 return a - b; });

九、高级应用

1.稳定排序模拟

javascript

// 如果需要绝对稳定(旧浏览器),可以添加索引 const data = [{value: 2}, {value: 1}, {value: 2}]; data .map((item, index) => ({item, index})) .sort((a, b) => { const valueDiff = a.item.value - b.item.value; if (valueDiff !== 0) return valueDiff; return a.index - b.index; // 保持原顺序 }) .map(({item}) => item);

2.多维度动态排序

javascript

function dynamicSort(properties) { return function(a, b) { for (const {property, order = 'asc'} of properties) { const aVal = a[property]; const bVal = b[property]; if (aVal < bVal) return order === 'asc' ? -1 : 1; if (aVal > bVal) return order === 'asc' ? 1 : -1; } return 0; }; } const items = [...]; items.sort(dynamicSort([ {property: 'category', order: 'asc'}, {property: 'price', order: 'desc'}, {property: 'name', order: 'asc'} ]));

3.性能基准测试

javascript

function benchmarkSort(arr, sortFn, iterations = 100) { const times = []; for (let i = 0; i < iterations; i++) { const copy = [...arr]; const start = performance.now(); sortFn(copy); const end = performance.now(); times.push(end - start); } return { avg: times.reduce((a, b) => a + b) / times.length, min: Math.min(...times), max: Math.max(...times), stdDev: Math.sqrt( times.map(t => Math.pow(t - avg, 2)) .reduce((a, b) => a + b) / times.length ) }; }

十、总结

最佳实践:

  1. 始终提供比较函数(除非明确需要字符串排序)

  2. 注意原地修改- 必要时先复制数组

  3. 复杂比较预计算- 提高性能

  4. 利用稳定性- 多条件排序依赖稳定排序特性

  5. 考虑数据特性- 部分有序数据 Timsort 表现更好


选择sort()当:

  • 需要稳定排序

  • 处理复杂对象

  • 代码简洁性优先

  • 数组大小适中(< 1百万)


考虑其他方案当:

  • 需要绝对性能(TypedArray)

  • 内存极度受限(堆排序)

  • 特殊数据结构(如链表)

  • 只需要部分排序(选择算法)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 0:26:51

JavaScript 中常用排序方法的性能对比和分析

一、原生数组排序方法 1. Array.prototype.sort() javascript // 默认排序&#xff08;按字符串Unicode码点&#xff09; arr.sort()// 自定义比较函数 arr.sort((a, b) > a - b) // 数字升序 时间复杂度&#xff1a; V8引擎&#xff1a;使用Timsort&#xff08;归并插入…

作者头像 李华
网站建设 2026/4/30 23:21:03

实力见证 | 尚医云·小济医生入选2025广州市“隐形冠军”企业名单

10月28日&#xff0c;以“冠军力量澎湃动能”为主题的2025广州市“隐形冠军”企业新质发展招商投资大会隆重召开。在这场汇聚产业精英的盛会上&#xff0c;尚医云小济医生凭借在人工智能超声筛查领域的源头创新与落地成果&#xff0c;成功入选2025广州市“隐形冠军”企业。图源…

作者头像 李华
网站建设 2026/4/30 23:21:03

Cordova与OpenHarmony施肥记录管理

欢迎大家加入开源鸿蒙跨平台开发者社区&#xff0c;一起共建开源鸿蒙跨平台生态。 施肥管理系统概述 施肥记录管理系统用于记录和追踪植物的施肥历史。在Cordova框架与OpenHarmony系统的结合下&#xff0c;我们需要实现一个完整的施肥管理系统&#xff0c;包括施肥记录的创建、…

作者头像 李华
网站建设 2026/5/1 0:33:32

娱乐or办公?何必二选一!移远云平板解决方案, 解锁智能终端新体验

在数字化生活与办公深度融合的今天&#xff0c;人们对于智能终端的需求日益多元——既希望拥有平板的便携与娱乐性&#xff0c;又需要电脑的高效生产力&#xff0c;同时追求性能、续航与体验的全面均衡。针对这一核心需求&#xff0c;移远通信重磅推出全新云平板解决方案。方案…

作者头像 李华
网站建设 2026/4/30 23:59:46

HuggingFace自定义模型接入Anything-LLM实战

掌控你的AI大脑&#xff1a;HuggingFace自定义模型接入Anything-LLM实战 在一家初创企业的技术晨会上&#xff0c;法务同事上传了一份长达80页的并购协议PDF&#xff0c;然后问&#xff1a;“这份合同里关于竞业禁止的条款具体覆盖哪些岗位&#xff1f;” 如果是过去&#xff0…

作者头像 李华