ES6Set和Map数据结构
Set是什么
Set 是 ES6 引入的一种集合(Collection)类型,特点是存储唯一值,不允许重复元素。有点像数组,但会自动去重。
Set没有下标去标示每一个值,所以Set是无序的,也不能像数组那样通过下标去访问Set的成员
const set = new Set();set.add(1);set.add(2);set.add(2);console.log(set);//Set(2) { 1, 2 }Set实例的方法和属性
常用方法
add() 添加元素
const set = new Set();set.add('Tom').add('Alex');set.add('Jerry');console.log(set);delete() 删除元素
set.delete('Tom');console.log(set);has()判断是否存在
const set = new Set([1, 2, 3]);console.log(set.has(2)); // trueconsole.log(set.has(4)); // falseclear()清空集合
set.clear();console.log(set.size); // 0size获取元素个数
const set = new Set([1, 2, 3]);console.log(set.size); // 3//类似数组的:arr.length遍历 Set获取元素值
for…of
const set = new Set([1, 2, 3]);
for (const item of set) { console.log(item);}forEach
set.forEach(item => { console.log(item);});//this指向谁,取决于外部环境,this 指向的是 外层作用域的 thisforEach的this指向问题
以下代码中:this指向谁:
const set = new Set();set.add('Tom').add('Alex');set.add('Jerry');
set.forEach((item) => { console.log(item);});//对象const obj = { name: 'A', run() { set.forEach((item) => { console.log(this.name); }); }};//classclass A { run() { set.forEach((item) => { console.log(this); }); }}//普通函数set.forEach(function(item) { console.log(this);});//普通函数,forEach第二个参数指定thisset.forEach(function(item) { console.log(this);}, obj);- 在浏览器普通脚本中:
this === window(非严格模式)或undefined(严格模式) - 在对象方法中:这里
this === obj - 在 class 中:this === 当前 class 实例
- 换成普通函数:默认:
undefined(严格模式),或window(非严格模式)或可以通过forEach 第二个参数指定
Set 与 Array 对比
| 特性 | Array | Set |
|---|---|---|
| 允许重复 | ✅ | ❌ |
| 按索引访问 | ✅ | ❌ |
| 自动去重 | ❌ | ✅ |
| 长度 | length | size |
| 查找元素 | includes() | has() |
Set构造函数的参数
Set 构造函数的参数是一个可迭代对象(iterable),用来初始化集合中的元素。
可以是任何可迭代对象,比如:Array(数组)、String(字符串)、Map(会取 key-value 中的 key)、Set、arguments、任何实现了 Symbol.iterator 的对象,如果不传参数,默认创建一个空 Set。
//数组const s = new Set([1, 2, 3]);console.log(s); // Set(3) {1, 2, 3}//自动去重(核心特性)const s = new Set([1, 1, 2, 2, 3]);console.log(s); // Set(3) {1, 2, 3}//字符串(按字符拆分)const s = new Set("hello");console.log(s); // Set(4) {'h','e','l','o'}//Map(只取 key)const m = new Map([ ["a", 1], ["b", 2]]);//Map(只取 key)const s = new Set(m);console.log(s); // Set(2) {'a', 'b'}//不传参数const s = new Set();console.log(s); // Set(0) {}Set 的注意事项
如何判断重复值
//注意点:Set 判断元素是否重复使用的是 SameValueZero(类似 ===,但 NaN 也相等)//对象引用不同即使内容一样也不会去重:const obj = new Set([{a:1}, {a:1}]) // 仍然是两个元素console.log(obj); // Set(2) { { a: 1 }, { a: 1 } }什么时候用Set
//数组或者字符串去重的时候//不需要通过下标访问,只需要遍历时//为了使用Set提供的方法和属性时(add delete clear has forEach size 等)Set的应用
黑名单:
const blacklist = new Set([ 'Tom', 'Jerry']);
if (blacklist.has(username)) { // 禁止访问}展开set
const s = new Set([1,2,3])console.log([...s]);字符串去重
const s = new Set(‘abbaerfghh’)console.log([...s].join(''));//去重之后,重新展开,重新转为字符串 数组的join()方法可以使数组转为字符串存放DOM元素
const selected = new Set(document.querySelectorAll("p"));selected.forEach(el => { el.style.color = "red";});Map是什么
Map 是 JavaScript 中的一种键值对集合结构,和普通对象 {} 类似,但功能更强、更规范。
const map = new Map();map.set('name', 'Alice');map.set('age', 18);console.log(map.get('name')); // AliceMap 和 Object 的核心区别
key 的类型更自由(Map 更强)
//Object key 只能是 字符串 / Symbolconst obj = {};obj[1] = "a";obj[true] = "b";console.log(obj); // key 会被转成字符串//Map key 可以是任何类型const map = new Map();map.set(1, "数字key");map.set(true, "布尔key");map.set({}, "对象key");
console.log(map.get(1)); // 数字keyMap 保持插入顺序
const map = new Map();map.set("a", 1);map.set("b", 2);map.set("c", 3);for (const [k, v] of map) { console.log(k, v);}Map 自带 size
const map = new Map();map.set("a", 1);map.set("b", 2);console.log(map.size); // 2Map 实例的属性和方法
常用方法
set(添加/修改)
map.set("name", "Tom");get(获取)
map.get("name");delete() 删除
map.delete("name");has()判断是否存在
map.has("name"); // trueclear()清空
map.clear();size获取个数
map.size();遍历Map获取元素值
for…of
for (const [key, value] of map) { console.log(key, value);}forEach(callback)
const map = new Map([ ["a", 1], ["b", 2]]);
map.forEach((value, key) => { console.log(key, value);//注意顺序是:value 在前,key 在后(和 set 不同)});keys / values / entries
for (const key of map.keys()) { console.log(key);}for (const value of map.values()) { console.log(value);}for (const entry of map.entries()) { console.log(entry);}for (const [k, v] of map) { console.log(k, v);}//map.keys();//map.values();//map.entries();Map 构造函数的参数
Map 构造函数的参数是一个可迭代对象(iterable),用于在创建 Map 时初始化键值对数据。
set、map、键值对数组
//数组,必须是二维结构const map = new Map([ ["name", "Alice"], ["age", 18]]);// new Map(["a", "b"]);//❌ 错误用法console.log(map.get("name")); // Alice
//由 Map 构造 Map(复制)相当于浅拷贝(key/value 引用不变)const m1 = new Map([ ["a", 1], ["b", 2]]);const m2 = new Map(m1);console.log(m2.get("a")); // 1
//Set ❌ 不能直接用(容易踩坑)new Map(new Set([1, 2, 3]));//❌ 错误用法Map 的注意事项
key 不会自动转换类型
const map = new Map();
map.set(1, "number");map.set("1", "string");
console.log(map.size); // 2,在 Object 里 "1" 和 1 可能会混在一起,但 Map 不会NaN 是相等的(特殊规则)
const map = new Map();
map.set(NaN, 1);map.set(NaN, 2);
console.log(map.size); // 1console.log(map.get(NaN)); // 2对象 key 比较的是“引用”
const map = new Map();
map.set({}, 1);map.set({}, 2);
console.log(map.size); // 2delete 返回值很重要
map.delete("a"); // true / false用来判断是否真的删除成功Map 不会自动去重 value
map.set("a", 1);map.set("b", 1);
console.log(map.size); // 2去重只针对 key,不针对 value如何判断键名是否相同:Map 的 key 判断遵循 ===
//基本类型(字符串/数字/布尔)相同 key(直接覆盖)map.set("a", 1);map.set("a", 2);
//NaN 特殊处理 认为相同 keymap.set(NaN, 1);map.set(NaN, 2);
//对象,引用比较,不相同(不同引用)map.set({a:1}, 1);map.set({a:1}, 2);
//同一个对象才算同一个 keyconst obj = {a:1};map.set(obj, 1);map.set(obj, 2);console.log(map.size); // 1什么时候用Map
//key 不是字符串时(必须用 Map)Object 做不到(会变成 "[object Object]")const map = new Map();const el = document.querySelector("div");map.set(el, { clicked: true });
//频繁增删数据;Map 比 Object 更稳定,不会触发 hidden class 变化map.set("a", 1);map.delete("a");
//需要有序数据结构;遍历顺序 = 插入顺序map.set("a", 1);map.set("b", 2);map.set("c", 3);
//需要快速查找 + 动态变化//缓存const cache = new Map();function getData(key) { if (cache.has(key)) return cache.get(key); const result = key * 2; cache.set(key, result); return result;}//DOM 状态管理const selected = new Map();selected.set(dom, true);
//需要避免 Object 原型污染Map 没有这个问题const obj = {};obj.__proto__ = "hack";什么时候不用 Map
//静态数据(推荐 Object)更简单 + JSON 友好const user = { name: "Alice", age: 18};//需要 JSON 序列化:Map 不能直接 stringify//简单配置数据 Object 更清晰Map的应用
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> /* p { background-color: orange; font-size: 40px; } */ </style> </head> <body> <p>1</p> <p>2</p> <p>3</p> <script> const p = document.querySelectorAll('p'); // console.log(p); //解构 const [p1, p2, p3] = document.querySelectorAll('p'); const m = new Map([ [p1, { color: 'red', backgroundColor: 'pink', fontSize: '40px' }], [p2, { color: 'blue', backgroundColor: 'orange', fontSize: '40px' }], [p3, { color: 'yellow', backgroundColor: 'green', fontSize: '40px' }], ]); m.forEach((propObject, elem) => { //console.log(propObject); for (const p in propObject) { // console.log(propObject); // console.log(p); // console.log(propObject[p]); elem.style[p] = propObject[p]; //elem.style.p = propObject[p]; 错误,这是静态调用 } }); </script> </body></html>把对象改为Map:
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> /* p { background-color: orange; font-size: 40px; } */ </style> </head> <body> <p>1</p> <p>2</p> <p>3</p> <script> const p = document.querySelectorAll('p'); // console.log(p); //解构 const [p1, p2, p3] = document.querySelectorAll('p'); const m = new Map([ [ p1, new Map([ ['color', 'red'], ['backgroundColor', 'pink'], ['fontSize', '40px'], ]), ],
[ p2, new Map([ ['color', 'blue'], ['backgroundColor', 'orange'], ['fontSize', '40px'], ]), ],
[ p3, new Map([ ['color', 'yellow'], ['backgroundColor', 'green'], ['fontSize', '40px'], ]), ], ]); m.forEach((styleMap, elem) => { styleMap.forEach((value, key) => { elem.style[key] = value; }); }); </script> </body></html>文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














