网站首页 > 技术文章 正文
数组去重是JavaScript中的一个常见的操作,随着ES6的普及,越来越多的前端开发者抛弃了传统的Array去重方法,转而使用Set来完成这项任务。这种转变不仅仅是因为代码更简洁,更重要的是性能上的巨大差异。
Set去重的简洁写法
在ES6出现之前,数组去重通常需要编写循环和条件判断:
function uniqueArray(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
if (result.indexOf(arr[i]) === -1) {
result.push(arr[i]);
}
}
return result;
}
// 使用
const array = [1, 2, 3, 3, 4, 4, 5];
const unique = uniqueArray(array); // [1, 2, 3, 4, 5]
而使用Set,代码可以简化为:
function uniqueArray(arr) {
return [...new Set(arr)];
}
// 使用
const array = [1, 2, 3, 3, 4, 4, 5];
const unique = uniqueArray(array); // [1, 2, 3, 4, 5]
但代码简洁只是表面优势,真正的价值在于性能提升。
性能对比:数字以为自己听错了
让我们通过几种常见的去重方法进行性能对比:
- Set方法
- 传统的indexOf方法
- 使用对象(Object)作为哈希表
- 使用Array.includes方法
- 使用filter + indexOf
测试方法
我们将创建不同大小的数组进行测试,每个数组包含随机生成的数字,并确保约有30%的元素是重复的:
function generateTestArray(size) {
const array = [];
for (let i = 0; i < size; i++) {
// 生成一定比例的重复元素
if (Math.random() > 0.7 && array.length > 0) {
// 从现有数组中随机选择一个元素作为重复元素
array.push(array[Math.floor(Math.random() * array.length)]);
} else {
// 生成一个新的随机元素
array.push(Math.floor(Math.random() * size * 10));
}
}
return array;
}
// 生成测试数组
const small = generateTestArray(100); // 100 个元素
const medium = generateTestArray(10000); // 10,000 个元素
const large = generateTestArray(1000000); // 1,000,000 个元素
console.log("Small:", small);
console.log("Medium:", medium);
console.log("Large:", large);
测试结果
以下是在不同大小数组上各方法的执行时间(单位:毫秒):
方法 | 100元素 | 10,000元素 | 1,000,000元素 |
Set | 0.05 | 1.2 | 85 |
Object哈希表 | 0.08 | 2.8 | 120 |
indexOf | 0.2 | 350 | 超过30秒 |
includes | 0.2 | 380 | 超过30秒 |
filter+indexOf | 0.3 | 800 | 超过60秒 |
在百万级数据上,Set比传统indexOf方法快了约300倍以上。
为什么Set如此高效?
Set之所以能提供如此惊人的性能优势,主要有以下几个原因:
1. 数据结构的本质区别
Set是基于哈希表实现的,这意味着:
- 查找、添加和删除操作的时间复杂度为O(1)
- 每个值在底层都有唯一的"地址",可以直接访问
而Array的indexOf和includes方法需要线性搜索,时间复杂度为O(n)。
2. 引擎优化
JavaScript引擎对Set进行了特殊优化:
- V8引擎中,Set使用哈希表和红黑树的组合实现
- Set在内存中的布局更适合现代CPU的缓存机制
- 引擎可以对Set操作应用更多底层优化
3. 自动处理边缘情况
Set能正确处理JavaScript中的特殊值:
const weirdArray = [0, -0, NaN, NaN, undefined, null, false, 0, ""];
console.log([...new Set(weirdArray)]);
// 输出:[0, NaN, undefined, null, false, ""
注意Set正确地将NaN与NaN视为相同(尽管NaN !== NaN),并且区分了0和"0"。
什么时候不应该使用Set?
尽管Set有许多优势,但也不是所有场景都适合:
- 需要保持原始顺序:虽然现代浏览器中Set是有序的(按插入顺序),但这并不是规范保证的
- 需要索引访问:Set不支持索引访问(如set[0])
- 需要频繁修改:如果需要频繁修改集合中的元素,数组的API可能更方便
- 处理非原始类型:对于对象等非原始类型,Set使用引用相等,可能不符合预期
最佳实践:Set和Array结合使用
现代前端开发中,一个常见的模式是Set和Array结合使用:
// 数据处理流程
constprocessData = (dataArray) => {
// 1. 去重
const uniqueData = [...newSet(dataArray)];
// 2. 使用数组方法进行处理
return uniqueData
.filter(item => item > 10)
.map(item => item * 2)
.sort((a, b) => a - b);
};
- 上一篇: 鸿蒙最终演示:前端的一些代码、服务端、数据库
- 下一篇: 心心念念的前端代码生成利器,前后端一网打尽
猜你喜欢
- 2025-04-27 【前端绝招】95%开发者不知道的10个神技巧!代码量直降50%!
- 2025-04-27 一起深入盘点 2025 年 React 发展的 10个趋势?
- 2025-04-27 讲解前端中 File、Blob、ArrayBuffer、Base64、DataURL
- 2025-04-27 心心念念的前端代码生成利器,前后端一网打尽
- 2025-04-27 鸿蒙最终演示:前端的一些代码、服务端、数据库
- 2025-04-27 前端请求一到,后端就乱套?揭秘 Spring MVC 底层调用全流程!
- 2025-04-27 炸裂!用这 5 个黑科技,前端性能直接狂飙 200%!附全网最细代码
- 2025-04-27 掌握这几个网页前端技巧,开发效率提升
- 2025-04-27 大厂前端架构师私藏:微前端落地最全避坑指南
- 2025-04-27 前端学习保姆级教程,轻松入门 Web 开发
你 发表评论:
欢迎- 最近发表
-
- 前端流行框架Vue3教程:13. 组件传递数据_Props
- 前端必看!10 个 Vue3 救命技巧,解决你 90% 的开发难题?
- JAVA和JavaScript到底是什么关系?是亲戚吗?
- Java和js有什么区别?(java和javascript的区别和联系)
- 东方标准|Web和Java的区别,如何选择这两个专业
- 前端面试题-JS 中如何实现大对象深度对比
- 360前端一面~面试题解析(360前端笔试)
- 加班秃头别慌!1 道 Vue 面试题,快速解锁大厂 offer 通关密码
- 焦虑深夜刷题!5 道高频 React 面试题,吃透 offer 稳了
- 2025Web前端面试题大全(整理版)面试题附答案详解,最全面详细
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端懒加载 (45)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle查询数据库 (45)
- oracle约束 (46)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)