小白也能懂的JavaScript新秘密:Set数据结构完全解析!

1. Set是什么?

Set,作为JavaScript中引入的一种新型数据结构,可以看作是一种集合,类似于数组,但具有一些独特的特性。最引人注目的特性之一是其成员的值是唯一的,即不允许重复值存在。这意味着你可以轻松地存储一组不同的元素,而不必担心重复。

ini 复制代码
const uniqueNumbers = new Set([1, 2, 3, 4, 4]);
console.log([...uniqueNumbers]); // [1, 2, 3, 4]

在上面的例子中,我们创建了一个Set实例uniqueNumbers,并通过传递一个包含重复元素的数组进行初始化。但是,由于Set的特性,最终我们得到的是一个包含唯一值的数组。

Set的独特之处不仅在于去重,它还提供了一系列便捷的方法来操作集合,例如添加、删除和检查元素的存在。

2. Set的基本用法

2.1 创建Set实例

要使用Set,首先需要创建一个Set实例。你可以通过new Set()来创建一个空的Set,也可以通过传递一个数组或其他可迭代对象进行初始化。

ini 复制代码
const colors = new Set(['red', 'green', 'blue']);

在上述例子中,我们创建了一个包含颜色名称的Set实例,用于演示接下来的基本用法。

2.2 添加、删除和判断元素

Set提供了简单而强大的方法来管理集合中的元素。

添加元素

使用add(value)方法可以向Set中添加元素。

css 复制代码
colors.add('yellow');
console.log([...colors]); // ['red', 'green', 'blue', 'yellow']

删除元素

使用delete(value)方法可以删除Set中的元素。

css 复制代码
colors.delete('green');
console.log([...colors]); // ['red', 'blue', 'yellow']

判断元素是否存在

使用has(value)方法可以检查Set中是否存在某个元素。

arduino 复制代码
console.log(colors.has('red')); // true
console.log(colors.has('green')); // false

2.3 遍历Set

Set提供了多种遍历方法,让你能够轻松检查集合中的所有元素。

css 复制代码
for (let color of colors) {
  console.log(color);
}

以上是Set的基本用法,它不仅仅可以帮助你管理不重复的数据,还能够优雅地进行各种操作。

3. Set的应用

3.1 去除数组重复元素

Set结合扩展运算符可以轻松去除数组的重复元素,是一种小巧却强大的应用。

c 复制代码
// 原始数组
const array = [3, 5, 2, 2, 5, 5];

// 使用 Set 数据结构去除数组中的重复元素
const uniqueArray = [...new Set(array)];

// 打印去重后的数组
console.log(uniqueArray); // [3, 5, 2]

在这个例子中,我们使用Set快速去除了数组array中的重复元素,得到了一个不含重复值的新数组uniqueArray

3.2 集合运算

Set在集合运算方面表现得非常出色,可以轻松实现并集、交集、差集等操作。

并集

javascript 复制代码
// 创建两个 Set,分别包含元素 [1, 2, 3] 和 [3, 4, 5]
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);

// 使用展开运算符和 Set 构造函数创建一个新的 Set,包含 setA 和 setB 的并集
const union = new Set([...setA, ...setB]);

// 打印合并后的 Set
console.log(union); // Set {1, 2, 3, 4, 5}

交集

javascript 复制代码
// 创建两个 Set,分别包含元素 [1, 2, 3] 和 [3, 4, 5]
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);

// 使用过滤器和 Set 构造函数创建一个新的 Set,包含 setA 和 setB 的交集
const intersect = new Set([...setA].filter((x) => setB.has(x)));

// 打印两个 Set 的交集
console.log(intersect); // Set {3}

解释:

  1. const setA = new Set([1, 2, 3]); - 创建一个 Set,包含元素 1, 2, 和 3。
  2. const setB = new Set([3, 4, 5]); - 创建另一个 Set,包含元素 3, 4, 和 5。
  3. [...setA].filter((x) => setB.has(x)) - 将 setA 转换为数组,然后使用 filter 方法过滤出在 setB 中也存在的元素,即交集。
  4. const intersect = new Set([...setA].filter((x) => setB.has(x))); - 使用 Set 构造函数创建一个新的 Set,其中包含 setA 和 setB 的交集。
  5. console.log(intersect); - 打印两个 Set 的交集,结果为 Set {3},即 setA 和 setB 共有的元素。

差集

javascript 复制代码
// 创建两个 Set,分别包含元素 [1, 2, 3] 和 [3, 4, 5]
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);

// 使用过滤器和 Set 构造函数创建一个新的 Set,包含 setA 和 setB 的差集
const difference = new Set([...setA].filter((x) => !setB.has(x)));

// 打印 setA 相对于 setB 的差集
console.log(difference); // Set {1, 2}

解释:

  1. const setA = new Set([1, 2, 3]); - 创建一个 Set,包含元素 1, 2, 和 3。
  2. const setB = new Set([3, 4, 5]); - 创建另一个 Set,包含元素 3, 4, 和 5。
  3. [...setA].filter((x) => !setB.has(x)) - 将 setA 转换为数组,然后使用 filter 方法过滤出在 setB 中不存在的元素,即 setA 相对于 setB 的差集。
  4. const difference = new Set([...setA].filter((x) => !setB.has(x))); - 使用 Set 构造函数创建一个新的 Set,其中包含 setA 相对于 setB 的差集。
  5. console.log(difference); - 打印 setA 相对于 setB 的差集,结果为 Set {1, 2},即 setA 中存在但 setB 中不存在的元素。

这些集合运算可以让你在处理数据时更加灵活,特别是在处理多个集合的情况下。

3.3 同步改变原Set结构

如果你想在遍历操作中同步改变原来的Set结构,可以使用映射方法或Array.from方法。

方法一:映射方法

dart 复制代码
// 创建一个 Set,包含元素 [1, 2, 3]
let set = new Set([1, 2, 3]);

// 使用映射和 Set 构造函数创建一个新的 Set,其中包含原 Set 中每个元素乘以 2 的结果
set = new Set([...set].map((val) => val * 2));

// 打印新的 Set,其中包含原 Set 中每个元素乘以 2 的结果
console.log(set); // Set {2, 4, 6}

方法二:Array.from方法

javascript 复制代码
// 创建一个 Set,包含元素 [1, 2, 3]
let set = new Set([1, 2, 3]);

// 使用 Array.from 和 Set 构造函数创建一个新的 Set,其中包含原 Set 中每个元素乘以 2 的结果
set = new Set(Array.from(set, (val) => val * 2));

// 打印新的 Set,其中包含原 Set 中每个元素乘以 2 的结果
console.log(set); // Set {2, 4, 6}

这些应用场景展示了Set在实际编程中的威力,为开发者提供了更多处理数据集合的可能性。

在下一部分,我们将进一步探索Set的高级用法,助你更深入地理解和应用这一强大的JavaScript数据结构。

4. 注意事项

在使用Set的过程中,有一些注意事项值得我们关注,确保我们能够充分利用这一强大的数据结构。

4.1 NaN的处理

Set内部判断两个值是否相等的算法与精确相等运算符稍有不同,特别是在处理NaN时。

ini 复制代码
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
console.log(set); // Set {NaN}

在上述例子中,我们向Set实例添加了两个NaN,但实际上它们被视为相等。这是因为在Set内部,两个NaN被认为是相等的。

4.2 对象的比较

两个对象总是不相等,即使它们的内容相同。

arduino 复制代码
let set = new Set();
set.add({});
console.log(set.size); // 1
set.add({});
console.log(set.size); // 2

在这个例子中,我们向Set中添加了两个空对象,由于两个对象不是精确相等,它们被视为两个不同的值。

4.3 Set的遍历顺序

Set的遍历顺序是按照插入顺序的,这一特性在某些场景下非常有用,比如保证回调函数列表按照添加顺序调用。

javascript 复制代码
const callbackList = new Set();
callbackList.add(() => console.log('Callback 1'));
callbackList.add(() => console.log('Callback 2'));
callbackList.add(() => console.log('Callback 3'));

for (let callback of callbackList) {
  callback();
}

在上述例子中,回调函数将按照它们被添加的顺序被调用。

结语

在使用Set时,我们需要注意其对NaN的处理、对象比较以及遍历顺序等特性,以确保我们的代码行为符合预期。Set作为JavaScript中强大的数据结构之一,为我们处理不重复值的场景提供了便捷而高效的解决方案。通过充分了解这些注意事项,我们能够更好地运用Set,提升编码效率和质量。

相关推荐
大家的林语冰22 分钟前
前端周刊:axios 疑遭朝鲜黑客“钓鱼“;CSS 新函数上线;npm 上线深色主题;Oxlint 兼容表;ESLint 支持 Temporal......
前端·javascript·css
哀木2 小时前
一个简单的套壳方案,就能让你的 Agent 少做重复初始化
前端
问心无愧05132 小时前
ctf show web入门27
前端
小村儿2 小时前
给 AI Agent 装上"长期记忆":Karpathy 的 LLM Wiki 思想,我做成了工具
前端·后端·ai编程
竹林8182 小时前
用ethers.js连接MetaMask实现Web3钱包登录:从踩坑到稳定运行的完整记录
前端·javascript
heyCHEEMS2 小时前
如何用 Recast 实现静态配置文件源码级读写
前端·node.js
心连欣2 小时前
从零开始,学习所有指令!
前端·javascript·vue.js
review445432 小时前
大模型和function calling分别是如何工作的
前端
东东同学2 小时前
耗时一个月,我把 Nuxt 首屏性能排障经验做成了一个 AI Skill
前端·agent
冴羽3 小时前
超越 Vibe Coding —— AI 辅助编程指南
前端·ai编程·vibecoding