JavaScript 中的Set从基础到高级用法
作者:风茫
本文全面介绍了ES6中Set数据结构的特点与用法,文章详细讲解了Set的创建、增删查API、遍历方法,并与Array进行性能对比,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
前言
在前端开发中,我们经常需要处理去重、集合运算、唯一性校验等需求。过去我们通常使用 Array 配合 filter + indexOf 或 reduce 来实现,但代码冗长且性能不佳。
为了解决这类问题,ES6 引入了 Set 数据结构。
本文将带你全面掌握 Set 的 定义、特性、API、使用场景、性能对比与最佳实践,助你在项目中高效处理“唯一性”问题。
一、什么是 Set?
定义
Set是一个 唯一值的集合,它允许存储任何类型的值,且每个值在集合中只出现一次。
const set = new Set();
核心特性
| 特性 | 说明 |
|---|---|
| 自动去重 | 重复添加的值会被忽略 |
| 大小可查 | set.size 直接获取元素数量 |
| 有序存储 | 按插入顺序遍历 |
| 无原型污染 | 不继承 Object.prototype,更“干净” |
| 性能更优 | 查找、插入、删除操作平均时间复杂度为 O(1) |
二、Set 的基本用法
1. 创建 Set
// 空 Set
const set = new Set();
// 从数组初始化(自动去重)
const set = new Set([1, 2, 3, 2, 1]); // Set { 1, 2, 3 }
// 从字符串创建(字符去重)
const charSet = new Set('hello'); // Set { 'h', 'e', 'l', 'o' }2. 增删查 API
| 方法 | 说明 | 返回值 |
|---|---|---|
add(value) | 添加值 | Set 本身(可链式调用) |
has(value) | 判断值是否存在 | boolean |
delete(value) | 删除值 | boolean(是否删除成功) |
clear() | 清空所有 | void |
const userSet = new Set();
userSet.add('Alice');
userSet.add('Bob');
userSet.add('Alice'); // 重复,忽略
console.log(userSet.has('Alice')); // true
console.log(userSet.delete('Bob')); // true
console.log(userSet.size); // 1
userSet.clear();
console.log(userSet.size); // 03. 链式调用
new Set() .add(1) .add(2) .add(3);
三、Set 的遍历方式
Set 提供了三种遍历方法,返回 迭代器(Iterator):
| 方法 | 返回值 | 说明 |
|---|---|---|
keys() | 值的迭代器 | 与 values() 相同(兼容 Map) |
values() | 值的迭代器 | 默认遍历方式 |
entries() | 键值对的迭代器 | 每个元素是 [value, value] |
1.for...of遍历
const set = new Set(['a', 'b', 'c']);
// 遍历值
for (const value of set) {
console.log(value);
}
// a
// b
// c
// 或使用 values()
for (const value of set.values()) {
console.log(value);
}
// 遍历键值对(每个键值相同)
for (const [key, value] of set.entries()) {
console.log(key, value); // a a, b b, c c
}2.forEach遍历
set.forEach((value, key) => {
console.log(value); // 注意:key === value
});
注意:
forEach的参数中key和value相同,这是为了与Map保持一致。
四、Set 与 Array 的对比
| 特性 | Set | Array |
|---|---|---|
| 唯一性 | 自动去重 | 允许重复 |
| 大小 | set.size | arr.length |
| 顺序 | 插入顺序 | 插入顺序 |
| 查找性能 | O(1) | O(n) |
| 序列化 | 需手动处理 | JSON.stringify() 支持 |
| 语法 | set.has(value) | arr.includes(value) |
何时使用 Set?
| 场景 | 推荐 |
|---|---|
| 去重 | Set(最优雅) |
| 频繁查找是否存在 | Set(性能优) |
| 需要保持唯一性 | Set |
需要索引访问(arr[0]) | Array |
需要 map、filter 等方法 | Array(需转换) |
| 数据量小、操作简单 | 可任选 |
五、Set 的高级用法
1. 数组去重(最简洁写法)
const arr = [1, 2, 2, 3, 3, 4]; const uniqueArr = [...new Set(arr)]; // [1, 2, 3, 4] // 或 const uniqueArr = Array.from(new Set(arr));
2. 集合运算(交集、并集、差集)
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
// 并集
const union = new Set([...a, ...b]); // {1, 2, 3, 4}
// 交集
const intersection = new Set([...a].filter(x => b.has(x))); // {2, 3}
// 差集(a - b)
const difference = new Set([...a].filter(x => !b.has(x))); // {1}3. 数组元素唯一性校验
const hasDuplicates = (arr) => {
return new Set(arr).size !== arr.length;
};
hasDuplicates([1, 2, 2]); // true
hasDuplicates([1, 2, 3]); // false4. 转换为 Array / Object
const set = new Set(['a', 'b', 'c']); // Set → Array const arr = [...set]; // ['a', 'b', 'c'] // 或 Array.from(set) // Array → Set const newSet = new Set(arr);
六、WeakSet:更轻量的 Set
什么是 WeakSet?
- 值必须是 对象
- 值是 弱引用,不会阻止垃圾回收
- 不能遍历,没有
size、clear()等 - 用于对象标记、私有数据、缓存
const ws = new WeakSet();
const obj = { name: 'Alice' };
ws.add(obj);
console.log(ws.has(obj)); // true
// 当 obj 被销毁,WeakSet 中的引用也会被自动清除与 Set 对比
| 特性 | Set | WeakSet |
|---|---|---|
| 值类型 | 任意 | 对象 |
| 弱引用 | 不支持 | 支持 |
| 可遍历 | 支持 | 不支持 |
size / clear() | 支持 | 不支持 |
| 用途 | 通用唯一集合 | 对象标记、缓存、私有数据 |
七、常见问题
1.Set和Array去重的区别?
答:
Set去重基于SameValueZero算法,NaN === NaN。Array的indexOf使用===,NaN !== NaN,无法去重NaN。Set性能更好,代码更简洁。
2.Set如何判断重复?
答:使用
SameValueZero比较算法:
===大部分情况- 特殊:
NaN被认为相等
const set = new Set([NaN, NaN]); console.log(set.size); // 1
3.WeakSet有什么用?
答:用于对象的临时标记、私有数据存储、避免内存泄漏。例如:
const disabledElements = new WeakSet(); disabledElements.add(button); // 当 button 被移除,标记自动消失
4. 如何实现对象内容去重?
答:需手动实现,如将对象序列化为字符串:
const objSet = new Set();
const key = JSON.stringify({ id: 1 });
objSet.add(key);
注意顺序、类型、
undefined处理。
总结
| 要点 | 说明 |
|---|---|
| 核心优势 | 自动去重、查找快(O(1))、有序、可查大小 |
| 适用场景 | 数组去重、集合运算、唯一性校验、缓存键 |
| 遍历方式 | for...of、forEach、values/entries |
| 转换方法 | [...set]、Array.from(set) |
| 内存优化 | WeakSet 用于对象的弱引用场景 |
到此这篇关于JavaScript 深入理解Set:从基础到高级用法的文章就介绍到这了,更多相关js set用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
