← JavaScript Map JavaScript 事件处理 →

JavaScript Set对象

原创 2026-03-23 JavaScript 已有人查阅

JavaScript Set 对象:处理唯一值的利器

在日常 JavaScript 开发中,我们经常需要处理一组数据,并且这组数据里不能有重复项。比如,收集用户标签、统计独立访客 ID,或者过滤掉数组里的重复值。以前我都是用对象来模拟,或者用数组配合 indexOf 或 includes 做去重,但代码写起来总是觉得不够直接。直到 ES6 带来了 Set 对象,这种场景处理起来就顺手多了。

Set 就是一个专门用来存储唯一值的。无论是数字、字符串,还是对象引用,它都能放,但会确保每个值只出现一次。如果你往 Set 里重复添加相同的值,它只会保留第一个。

什么是 Set?

简单来说,Set 是一种数据结构,它内部维护着一组唯一的元素。当你需要确保数据不重复时,它就是很合适的选择。

语法

new Set([iterable])
  • iterable:可选参数。如果传入一个可迭代对象(比如数组),这个对象里的所有元素会被添加到新建的 Set 中。重复的值会自动被忽略。

Set 的几个关键特点

在使用中,我发现下面这几点是理解 Set 的关键:

  1. 值的唯一性:这是 Set 最根本的特性。它内部会用一种严格相等(===)的逻辑来判断值是否重复。NaN 在 Set 中被视为相等的,即使 NaN === NaN 的结果是 false

  2. 有序性Set 会按照元素被添加的顺序来存储它们。当你遍历 Set 时,输出的顺序就是插入的顺序。

  3. 键与值相同Set 内部实现其实用了“键”的概念,但每个键的值就是键本身。所以你看到 entries() 方法返回的是 [value, value] 这样的形式,这在刚开始接触时可能会觉得有点特别,但理解了它的设计意图后就能明白。

Set 的创建与使用

下面我们通过一些例子,在“代码号”学习场景里看看 Set 具体怎么用。

1. 创建 Set

创建一个空的 Set,或者用数组来初始化。

// 代码号学习笔记:创建Set
let emptySet = new Set();
console.log(emptySet); // 输出: Set(0) {}

// 用数组初始化,重复的值会被自动过滤
let fruitSet = new Set(['苹果', '香蕉', '苹果', '橙子', '香蕉']);
console.log(fruitSet); 
// 输出: Set(3) { '苹果', '香蕉', '橙子' }
2. 添加元素:add() 方法

用 add() 往 Set 里添加元素。如果添加一个已经存在的值,什么也不会发生。

// 代码号学习笔记:add() 添加元素
let userIds = new Set();
userIds.add(1001);
userIds.add(1002);
userIds.add(1001); // 重复添加,无效

console.log(userIds); // 输出: Set(2) { 1001, 1002 }
console.log(userIds.size); // 输出: 2,size属性可以获取元素个数
3. 检查元素是否存在:has() 方法

在操作之前,经常需要先确认某个值是否已经在里了。has() 方法就是用来做这个的。

// 代码号学习笔记:has() 检查元素是否存在
let activeUsers = new Set(['alice', 'bob', 'carol']);

if (activeUsers.has('alice')) {
    console.log('alice 是活跃用户');
}
// 输出: alice 是活跃用户

console.log(activeUsers.has('dave')); // 输出: false
4. 删除元素:delete() 方法

从 Set 中移除一个元素,用 delete()。它会返回一个布尔值,告诉你是否删除成功。

// 代码号学习笔记:delete() 删除元素
let tags = new Set(['前端', 'JavaScript', '教程']);

let removed = tags.delete('JavaScript');
console.log(removed); // 输出: true
console.log(tags);    // 输出: Set(2) { '前端', '教程' }

// 删除一个不存在的元素
removed = tags.delete('后端');
console.log(removed); // 输出: false
5. 清空 Set:clear() 方法

如果想一次性清空所有元素,clear() 是最直接的方式。

// 代码号学习笔记:clear() 清空
let tempSet = new Set([1, 2, 3]);
console.log(tempSet.size); // 输出: 3
tempSet.clear();
console.log(tempSet.size); // 输出: 0
6. 遍历 Set:values()keys()entries() 与 forEach()

Set 提供了多种遍历方式。值得一提的是,keys() 和 values() 在 Set 中的行为是一样的,都返回值的迭代器。

// 代码号学习笔记:遍历Set
let scores = new Set([88, 92, 75, 100]);

// 使用 values() 或 keys() 遍历
console.log('--- 遍历值 ---');
for (let score of scores.values()) {
    console.log(score);
}
// 输出: 88, 92, 75, 100

// 使用 entries(),每个元素返回 [value, value]
console.log('--- entries() 遍历 ---');
for (let entry of scores.entries()) {
    console.log(entry);
}
// 输出: [88, 88], [92, 92], [75, 75], [100, 100]

// 使用 forEach
console.log('--- forEach 遍历 ---');
scores.forEach((value, key) => {
    // 注意,这里的 key 和 value 是相同的
    console.log(`${key}: ${value}`);
});
// 输出: 88: 88, 92: 92, 75: 75, 100: 100

实用场景:用 Set 给数组去重

在开发中,我经常用 Set 来处理数组去重,这是它最实用的场景之一。以前需要写循环或者用 filter,现在一行代码就能搞定。

// 代码号学习笔记:Set 给数组去重
let originalArray = [1, 2, 2, 3, 4, 4, 5, 1];
let uniqueArray = [...new Set(originalArray)];

console.log(uniqueArray); // 输出: [1, 2, 3, 4, 5]

经验之谈:Set 与数组的取舍

有同学可能会问,数组也能存储数据,为什么还要用 Set?我个人的经验是,两者的侧重点不同:

  • 如果你关心的是“值是否重复”,并且需要频繁检查某个值是否存在,那 Set 更合适。Set 的 has() 方法在性能上通常比数组的 includes() 要好,尤其是数据量较大的时候。Set 内部实现的数据结构(类似哈希表)让查找效率更高。

  • 如果你关心的是“顺序”和“索引”,并且需要对元素进行排序、过滤、映射等操作,那数组更合适。数组有丰富的 mapfilterreduce 方法,而 Set 在这方面就比较基础。

  • 如果你需要存储一组唯一值,但又需要用到数组的方法,通常的做法是先转成数组处理完再转回 Set。我平时经常这样用,既保证了唯一性,又不丢失数组操作的灵活性。

本节课程知识要点

  1. 值的唯一性Set 内部使用严格相等(===)来判断重复,NaN 在 Set 中被视为相等,这是一个需要注意的细节。

  2. 插入顺序Set 的迭代顺序就是元素被添加的顺序,这在进行数据展示或需要保持原始顺序时很有用。

  3. size 属性:获取 Set 中元素的数量,直接使用 set.size 即可,比数组的 length 更直观,也比对象的 Object.keys().length 更高效。

  4. 键值同构Set 的 keys() 和 values() 方法返回相同的迭代器,entries() 返回 [value, value] 的键值对,这是为了保持与 Map 接口的一致性。

  5. 应用场景:数组去重、管理不重复的 ID 、标签系统、数据过滤等场景,都是 Set 比较合适的使用场景。

← JavaScript Map JavaScript 事件处理 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号