当前位置: 首页 > news >正文

ES6 Set和Map用法详解(附实例+避坑指南)

在ES6之前,JavaScript中用于存储数据的主要结构是对象(Object)和数组(Array),但它们在某些场景下存在明显局限性:比如对象的键只能是字符串或Symbol,数组无法快速去重,查找元素效率较低。为了解决这些问题,ES6引入了两种新的数据结构——Set和Map,它们分别对应“无重复值的集合”和“键值对映射”,在实际开发中(尤其是前端框架、数据处理场景)应用广泛。本文将详细讲解Set和Map的核心用法、实例场景及常见误区,帮助大家快速上手。

一、Set 用法详解

1.1 什么是Set?

Set是一种无序、唯一的集合,它里面的每个元素都是唯一的,没有重复值。Set本身是一个构造函数,用来生成Set实例。

核心特点:

  • 元素不重复,自动去重

  • 无序(不保证插入顺序与遍历顺序一致,与Object不同,Object在ES6后虽有顺序,但本质是“伪有序”)

  • 可以存储任意类型的值(包括基本类型和引用类型)

  • 没有索引,无法通过下标访问元素

1.2 Set 基本用法(创建+增删改查)

1.2.1 创建Set实例

可以通过两种方式创建Set:空实例,或传入可迭代对象(数组、字符串等)初始化。

// 1. 创建空

Set const s1 = new Set();

// 2. 传入数组初始化(自动去重)

const s2 = new Set([1, 2, 2, 3, 3, 3]);

console.log(s2); // Set(3) {1, 2, 3}

// 3. 传入字符串初始化(自动去重)

const s3 = new Set('hello');

console.log(s3); // Set(4) {'h', 'e', 'l', 'o'}(l重复被去重)

// 4. 传入其他可迭代对象(如Map、Set本身)

const s4 = new Set(s2); console.log(s4); // Set(3) {1, 2, 3}(复制一个Set)

1.2.2 核心方法(增删改查)

Set的方法较少,常用的只有6个,记住即可灵活使用:

方法

作用

示例

add(value)

添加元素,返回Set本身(可链式调用)

s1.add(1).add(2)

delete(value)

删除指定元素,返回布尔值(成功true,失败false)

s2.delete(2) // true

has(value)

判断元素是否存在,返回布尔值

s2.has(3) // true

clear()

清空所有元素,无返回值

s2.clear()

size

属性,获取Set的元素个数(类似数组length)

console.log(s2.size) // 3

forEach()

遍历Set,回调函数接收(value, key, Set本身)

s2.forEach((val) => console.log(val))

1.2.3 注意事项(避坑点)

Set的“去重”是基于“严格相等(===)”判断的,有两个特殊情况:

  1. NaN和NaN被认为是相等的(虽然NaN === NaN为false,但Set中会去重)

  2. undefined和undefined相等,null和null相等

  3. 引用类型(对象、数组)即使内容相同,也会被认为是不同元素(因为引用地址不同)

const s = new Set();

s.add(NaN); s.add(NaN);

console.log(s); // Set(1) {NaN}(去重成功)

s.add({a: 1}); s.add({a: 1});

console.log(s); // Set(2) {{a:1}, {a:1}}(去重失败,引用地址不同)

1.3 Set 实际应用场景

Set的核心优势是“自动去重”和“快速查找”,常见应用场景:

  1. 数组去重(最常用)const arr = [1, 2, 2, 3, 4, 4, 5];const uniqueArr = [...new Set(arr)]; // [1,2,3,4,5]// 或 Array.from(new Set(arr))

  2. 判断元素是否存在(效率比数组indexOf高,尤其是数据量大时)

  3. 存储不重复的标识(如用户ID、商品ID)

  4. 数组交集、并集、差集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}

二、Map 用法详解

2.1 什么是Map?

Map是一种有序的键值对集合,它的键可以是任意类型(包括基本类型、引用类型),这解决了Object键只能是字符串/Symbol的局限性。Map的键是唯一的,值可以重复。

核心特点:

  • 键可以是任意类型(字符串、数字、对象、Symbol等)

  • 有序(插入顺序与遍历顺序一致,这是与Object的核心区别之一)

  • 键唯一,值可以重复

  • 可以通过键快速查找值,效率比Object高(尤其是频繁增删改查场景)

2.2 Map 基本用法(创建+增删改查)

2.2.1 创建Map实例

Map可以通过空实例创建,或传入“二维数组”(每一项是[key, value])初始化,也可以传入其他Map实例复制。

// 1. 创建空Map

const m1 = new Map();

// 2. 传入二维数组初始化

const m2 = new Map([ ['name', '张三'], [18, '年龄'], [{a: 1}, '对象键'], [Symbol('id'), 1001] ]);

console.log(m2); // Map(4) {'name' => '张三', 18 => '年龄', {a:1} => '对象键', Symbol(id) => 1001}

// 3. 复制Map

const m3 = new Map(m2);

console.log(m3); // 与m2内容一致

2.2.2 核心方法(增删改查)

Map的常用方法比Set多一些,重点记住以下7个:

方法/属性

作用

示例

set(key, value)

添加/修改键值对(键存在则修改值,不存在则添加),返回Map本身(可链式调用)

m1.set('name', '李四').set('age', 20)

get(key)

获取指定键的值,键不存在返回undefined

m2.get('name') // '张三'

delete(key)

删除指定键值对,返回布尔值(成功true,失败false)

m2.delete(18) // true

has(key)

判断键是否存在,返回布尔值

m2.has({a:1}) // false(引用地址不同)

clear()

清空所有键值对,无返回值

m2.clear()

size

属性,获取Map的键值对个数

console.log(m2.size) // 4

forEach()

遍历Map,回调函数接收(value, key, Map本身)

m2.forEach((val, key) => console.log(key, val))

2.2.3 注意事项(避坑点)

1. Map的键唯一性判断,与Set一致,基于“严格相等(===)”,但有两个特殊情况:

  • NaN和NaN视为同一个键

  • 引用类型的键,即使内容相同,只要引用地址不同,就是不同的键

2. Map与Object的区别(高频面试题):

  • 键的类型:Map键可以是任意类型,Object键只能是字符串/Symbol

  • 顺序:Map有序,Object(ES6前无序,ES6后伪有序)

  • 遍历:Map可直接遍历,Object需要手动遍历(如for...in)

  • 大小:Map可通过size属性获取,Object需要手动计算(Object.keys(obj).length)

  • 性能:Map在频繁增删改查场景下,性能优于Object

const m = new Map();

const obj1 = {a: 1};

const obj2 = {a: 1};

m.set(obj1, 'test1'); m.set(obj2, 'test2');

console.log(m.get(obj1));

// 'test1' console.log(m.get(obj2)); // 'test2'(两个对象键不同)

2.3 Map 实际应用场景

Map的核心优势是“键可以是任意类型”和“有序性”,常见应用场景:

  1. 存储复杂键值对(如用对象作为键,关联对应的数据)// 示例:用DOM元素作为键,存储对应的状态const btn = document.querySelector('button');const stateMap = new Map();stateMap.set(btn, {disabled: false, text: '点击'});// 后续获取按钮状态console.log(stateMap.get(btn).disabled); // false

  2. 需要保持键值对顺序的场景(如表单字段、配置项)

  3. 频繁增删改查的场景(如购物车数据、用户会话信息)

  4. 替代Object存储多类型键的场景(避免键被自动转为字符串)

三、Set和Map的区别总结

很多开发者会混淆Set和Map,这里用一张表格清晰区分,方便记忆:

对比维度

Set

Map

数据结构

无重复值的集合(只有值,无键)

键值对集合(键-值映射)

核心作用

去重、判断元素存在

存储键值对、通过键快速查找值

元素特点

值唯一,无序

键唯一,值可重复,有序

常用方法

add、delete、has、clear

set、get、delete、has、clear

遍历方式

forEach、for...of

forEach、for...of(可遍历键、值、键值对)

四、总结

Set和Map是ES6中非常实用的数据结构,它们弥补了Object和Array的不足,在实际开发中可以根据场景灵活选择:

  • 如果需要去重、判断元素是否存在,用Set(如数组去重、存储唯一标识);

  • 如果需要存储键值对、用非字符串作为键,用Map(如复杂数据映射、保持键值对顺序)。

掌握它们的基本用法和避坑点,能让我们的代码更简洁、高效,尤其是在处理大量数据、复杂映射场景时,能显著提升开发效率。建议大家动手实践文中的实例,加深理解~

最后,如果你觉得本文对你有帮助,欢迎点赞、收藏,关注我,后续分享更多ES6实用技巧!

http://www.cnnetsun.cn/news/1392597.html

相关文章:

  • OpenClaw自动化测试:结合QwQ-32B实现智能测试用例生成
  • 密码学算法 - 连分数算法
  • Ostrakon-VL-8B实操手册:自定义ShopBench子集评估模型在本地门店数据表现
  • OpenClaw日志分析:Qwen3-32B实时监控系统日志并发送告警
  • 告别云端上传:用FilePizza实现浏览器直连的P2P文件传输
  • 告别ChatGPT!Qwen3-4B暗黑WebUI体验:免费高智商AI写作助手
  • 2026年AI提示词(Prompt)终极指南:国内聚合站实战技巧
  • HAR实战指南:从Kinetics-400数据集获取到视频帧预处理全流程解析
  • ESP32嵌入式固件骨架:基于tcMenu的工程级基础库
  • 【独家首发】MCP 2.0安全架构设计图完整标注版(含17个攻击面标记+9个CWE编号映射):从威胁建模到自动化检测脚本一键生成
  • Java+ElasticSearch+Pytorch实战:手把手教你搭建一个简易版Google以图搜图系统
  • OpenClaw跨平台控制:GLM-4.7-Flash同步管理多台设备任务
  • 电脑控制手机!免安装! 上班族狂喜!手机投屏软件推荐
  • Dev-C++怀旧与启示:从轻量IDE看Phi-3-vision模型轻量化部署趋势
  • 硬件工程师成长路径:从电路直觉到系统思维
  • Lingbot-Depth-Pretrain-ViTL-14数据库联动实战:深度数据存储与MySQL管理
  • RVC常见问题解决:训练失败、效果不佳怎么办?排查指南来了
  • 银河麒麟系统下Miniconda安装避坑指南:解决Permission denied错误
  • TreeATE vs 传统测试工具:开源自动化测试平台在工业物联网中的优势解析
  • Axure RP 中文语言包部署指南:提升原型设计效率的本地化解决方案
  • C盘空间可视化工具哪个好?实测这款免费神器,一键清理30GB垃圾
  • NCP5623 RGB LED驱动库深度解析与低功耗实践
  • Qwen3-0.6B-FP8效果展示:FP8下长文档摘要保持关键事实与逻辑完整性
  • 保姆级教程:基于Gradio快速搭建Qwen3-ASR-0.6B语音识别Web应用
  • Neeshck-Z-lmage_LYX_v2入门必看:LoRA权重文件命名规范与目录结构建议
  • # 发散创新:基于WebRTC的实时音视频通信在前端应用中的深度实践在
  • Qwen3.5-9B智能体任务演示:自动订机票+查天气+生成行程表全流程视频
  • 1.两数之和-day1
  • Phi-3-vision-128k-instruct赋能运维:自动化分析服务器监控图表与日志截图
  • EffctiveC++_02第二章