news 2026/6/14 9:42:18

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/6/12 5:40:36

BioSIM 抗人 IL-1b 抗体SIM0362:多种应用兼容性,适应多样化实验需求

在免疫学与炎症研究领域&#xff0c;IL-1b&#xff08;白细胞介素-1b&#xff09;作为关键的促炎因子&#xff0c;其作用机制和调控方式一直是科研关注的焦点。为了更好地理解这一重要分子的功能&#xff0c;研究人员需要高度特异、性能稳定的抗体工具。BioSIM 抗人 IL-1b 抗体…

作者头像 李华
网站建设 2026/6/12 1:41:25

清理linux大文件

最近我有几台机器的日志太多了。。。也不是重要系统可以删掉log文件。删到最后没有可以删除的了。于是使用了 find /path/to/directory -type f -size 100M查出来发现是docker的日志太大了&#xff0c;这个日志一直都是默认状态&#xff0c;所以一直都没有进行处理。 truncat…

作者头像 李华
网站建设 2026/6/12 12:03:26

纸质档案存隐患?档案宝全生命周期电子化管理

在企业日常运营中&#xff0c;档案管理是不可或缺的基础工作&#xff0c;合同文件、财务凭证、人事资料、项目报告等各类档案承载着组织的核心信息&#xff0c;其管理质量直接影响企业运营效率与风险防控能力。然而&#xff0c;传统纸质档案管理模式长期以来存在诸多难以解决的…

作者头像 李华
网站建设 2026/6/11 16:55:26

Python+AI 打造每日新闻简报应用(聚合热搜 + 智能摘要 + 语音播报)

一、教程概述 本教程将带你从零搭建一款 AI 驱动的每日新闻简报应用「Briefy」&#xff0c;核心功能包括聚合多平台热搜、AI 智能摘要、语音播报&#xff0c;最终实现 “5 分钟掌握全网热点” 的高效信息获取工具。适合有 Python 基础、对 AI 应用开发感兴趣的开发者&#xff…

作者头像 李华
网站建设 2026/6/14 7:19:23

JUnit 5 中的 @ClassTemplate 实战指南

当你在本地、测试环境和 CI 中跑同一组测试时&#xff0c;是否遇到过这样的困惑&#xff1a;同一段业务逻辑在不同配置、不同 Locale 下的表现不尽相同&#xff0c;但你又不想为每种场景复制一堆几乎一样的测试类&#xff1f;如果把所有分支逻辑都塞进一个测试方法里&#xff0…

作者头像 李华
网站建设 2026/6/14 4:44:20

Parasoft Jtest 如何用 JSON 文件驱动Java 测试自动化

在金融、汽车、医疗等对可靠性与合规性要求较高的行业&#xff0c;Java 应用中的代码缺陷可能直接导致资金损失、服务中断或监管处罚。Parasoft Jtest 是一款企业级 Java 自动化测试平台&#xff0c;支持静态代码分析、智能单元测试生成、代码覆盖率评估以及合规规则检查。其内…

作者头像 李华