1. Map
1.1 Map 的定义
Map 是一个包含键值对的集合,键和值都可以是任何类型。与普通的 JavaScript 对象不同,Map 的键可以是任何数据类型,而不仅仅是字符串或符号。
1.2 Map 的基本特性
- 任意类型的键:在 
Map中,键可以是任意类型的数据,包括对象、函数、甚至其他Map实例。 - 有序性:
Map会按照插入的顺序存储键值对,因此可以保证迭代的顺序。 - 键值对存储:
Map存储的是键值对,键和值都可以是任何类型的对象。 - 大小:
Map有一个size属性,可以返回Map中键值对的数量。 - 迭代:
Map本身是可迭代的,支持forEach循环和其他迭代方法(如for...of)。 - 性能:与对象相比,
Map在进行大量操作时,尤其是当涉及到非字符串类型的键时,通常性能更好。 
1.3 Map 的常用方法
set(key, value):设置键值对,如果键已存在,则更新值。
js 代码解读复制代码  let map = new Map();
  map.set('a', 1);
  map.set('b', 2);
get(key):根据键获取值,如果键不存在返回undefined。
js 代码解读复制代码  console.log(map.get('a')); // 1
  console.log(map.get('c')); // undefined
has(key):判断Map中是否包含指定的键。
js 代码解读复制代码  console.log(map.has('a')); // true
  console.log(map.has('c')); // false
delete(key):删除指定键的键值对,返回true或false,表示删除成功或键不存在。
js 代码解读复制代码  map.delete('a'); // true
  map.delete('c'); // false
clear():清空Map中所有的键值对。
js 代码解读复制代码  map.clear(); // 清空 Map
size:返回Map中键值对的数量。
js 代码解读复制代码  console.log(map.size); // 2
- 迭代方法:
forEach(callback):对Map中的每一个元素执行callback函数。javascript map.forEach((value, key) => { console.log(key, value); });keys():返回一个包含所有键的迭代器。values():返回一个包含所有值的迭代器。entries():返回一个包含所有键值对的迭代器。
 
1.4 Map 示例
js 代码解读复制代码let map = new Map();
// 添加键值对
map.set('name', 'Alice');
map.set(1, 'Number');
map.set(true, 'Boolean');
// 获取值
console.log(map.get('name')); // Alice
console.log(map.get(1)); // Number
// 判断键是否存在
console.log(map.has('name')); // true
console.log(map.has('age')); // false
// 删除键值对
map.delete(1); // 删除键为 1 的元素
console.log(map.size); // 2
// 遍历 Map
map.forEach((value, key) => {
  console.log(key, value);
});
2. WeakMap
2.1 WeakMap 的定义
WeakMap 是一种类似于 Map 的数据结构,它存储的是键值对,但与 Map 不同的是,WeakMap 中的键必须是对象类型,且键是 弱引用。这意味着,WeakMap 不会阻止其键对象被垃圾回收。
2.2 WeakMap 的基本特性
- 键必须是对象:
WeakMap的键只能是对象类型(包括数组、函数等),不能是基本数据类型(如字符串、数字等)。 - 弱引用:
WeakMap中的键是弱引用,这意味着如果没有其他引用指向这个对象,垃圾回收器可以回收这些键值对。 - 不支持迭代:
WeakMap不支持像Map一样进行迭代,因为它的键是弱引用,可能会被垃圾回收,因此无法保证迭代顺序。 - 内存管理:
WeakMap可以帮助管理内存,尤其是在存储大量数据时,可以避免不再使用的对象继续占用内存。 
2.3 WeakMap 的常用方法
set(key, value):设置键值对,键必须是对象。
js 代码解读复制代码  let weakMap = new WeakMap();
  let obj = {};
  weakMap.set(obj, 'Some value');
get(key):根据键获取值,如果键不存在返回undefined。
js 代码解读复制代码  console.log(weakMap.get(obj)); // 'Some value'
has(key):判断WeakMap中是否包含指定的键。
js 代码解读复制代码  console.log(weakMap.has(obj)); // true
delete(key):删除指定键的键值对,返回true或false,表示删除成功或键不存在。
js 代码解读复制代码  weakMap.delete(obj); // true
2.4 WeakMap 示例
js 代码解读复制代码let weakMap = new WeakMap();
let obj1 = {};
let obj2 = {};
// 添加键值对
weakMap.set(obj1, 'Value 1');
weakMap.set(obj2, 'Value 2');
// 获取值
console.log(weakMap.get(obj1)); // 'Value 1'
// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // false
// 垃圾回收:当 obj1 没有其他引用时,weakMap 中的键会自动被删除
3. Map 与 WeakMap 的区别
| 特性 | Map | WeakMap | 
|---|---|---|
| 键的类型 | 可以是任何类型(包括对象、函数等) | 键必须是对象类型 | 
| 垃圾回收 | 键值对不会被垃圾回收机制影响 | 键是弱引用,可以被垃圾回收 | 
| 支持迭代 | 支持 forEach、keys()、values()、entries() | 不支持迭代 | 
| 大小 | 可以通过 .size 获取大小 | 不支持获取大小 | 
| 内存管理 | 不适用于内存敏感应用 | 更适合内存管理,避免对象泄漏 | 
- Map:适合需要频繁插入、删除和访问的场景,支持任意类型的键,支持迭代,且键值对在内存中常驻,直到被显式删除。
 - WeakMap:适合需要存储对象的场景,尤其是在需要避免对象因被 
Map引用而无法垃圾回收的情况。由于键是弱引用,WeakMap有助于内存管理,但不支持迭代,也没有size属性。 
4. Set
Set 是 ES6 引入的一种集合数据结构,用于存储一组唯一值,没有重复元素。
4.1 Set 的基本特点
- 唯一性:
Set中的元素是唯一的,不能重复。如果你尝试插入重复的元素,它会自动忽略。 - 顺序性:
Set保留插入元素的顺序。你插入的顺序就是遍历时的顺序。 - 可迭代:
Set是可迭代的,支持for...of和其他迭代方法进行遍历。 - 类型:
Set可以存储任何类型的值,包括原始类型(如数字、字符串)和对象类型(如数组、对象)。 - 无索引访问:不像数组,
Set不支持通过索引访问元素。 
4.2 常用方法
add(value):向Set中添加一个元素。如果该元素已存在,Set会忽略它。
js 代码解读复制代码   let set = new Set();
   set.add(1);
   set.add(2);
   set.add(1);  // 不会添加,重复的元素会被忽略
   console.log(set);  // Set { 1, 2 }
has(value):检查Set中是否包含指定的元素。
js 代码解读复制代码   console.log(set.has(1));  // true
   console.log(set.has(3));  // false
delete(value):删除Set中的指定元素。
js 代码解读复制代码   set.delete(1);
   console.log(set);  // Set { 2 }
clear():清空Set中的所有元素。
js 代码解读复制代码   set.clear();
   console.log(set);  // Set {}
size:返回Set中元素的数量。
js 代码解读复制代码   console.log(set.size);  // 2
forEach(callback):对Set中的每个元素执行一个回调函数。
js 代码解读复制代码   set.forEach(value => console.log(value));  // 输出 1 和 2
values():返回一个包含Set中所有值的迭代器对象。
js 代码解读复制代码   let iterator = set.values();
   console.log(iterator.next().value);  // 1
4.3 Set 的使用场景
- 去重:
Set最常见的用途之一是去重。通过将一个数组转换为Set,我们可以轻松去除其中的重复元素。 
js 代码解读复制代码  let arr = [1, 2, 2, 3, 4, 4, 5];
  let uniqueArr = [...new Set(arr)];
  console.log(uniqueArr);  // [1, 2, 3, 4, 5]
- 集合运算:
Set可以很方便地进行集合的交集、并集和差集等运算。- 并集:可以通过将两个 
Set合并来实现并集。 - 交集:通过过滤操作来获取交集。
 - 差集:通过过滤操作来获取差集。
 
 - 并集:可以通过将两个 
 
5. WeakSet
WeakSet 是 Set 的一个变种,主要用于存储对象的引用,并且这些引用是弱引用,意味着当没有其他地方引用这些对象时,它们会被自动清除。
5.1 WeakSet 的基本特点
- 只能存储对象:
WeakSet只能存储对象,不能存储原始数据类型(如数字、字符串、布尔值等)。 - 弱引用:
WeakSet中的元素是弱引用的。如果没有其他引用指向这些对象,它们会在垃圾回收时自动删除。 - 不支持遍历:
WeakSet没有提供迭代器方法,如forEach()、values()、keys()等,因此不能像Set一样遍历元素。 - 没有 
clear()方法:由于元素是弱引用的,WeakSet不需要清除操作,它们会在没有其他引用时被垃圾回收。 
5.2 常用方法
add(value):向WeakSet中添加一个对象。元素必须是对象类型。
ini 代码解读复制代码   let ws = new WeakSet();
   let obj = {};
   ws.add(obj);
has(value):检查WeakSet中是否包含指定的对象。
arduino 代码解读复制代码   console.log(ws.has(obj));  // true
delete(value):删除WeakSet中的指定对象。
scss 代码解读复制代码   ws.delete(obj);
   console.log(ws.has(obj));  // false
5.3 WeakSet 的使用场景
内存管理:WeakSet 在内存管理中非常有用,因为它允许对象在没有其他引用时被垃圾回收。它非常适合用于存储和跟踪需要在某个时刻“标记”的对象。
- 比如,你可以用 
WeakSet来标记某个对象是否已被处理,但不会阻止这些对象被垃圾回收。 
ini 代码解读复制代码  let ws = new WeakSet();
  let obj1 = {};
  let obj2 = {};
  ws.add(obj1);
  console.log(ws.has(obj1));  // true
  obj1 = null;  // 释放 obj1 的引用
  // obj1 被垃圾回收,不再出现在 WeakSet 中
- 避免内存泄漏:
WeakSet很适合用来避免内存泄漏,特别是在事件监听或对象管理的场景中,防止对象无法被回收。 
5.4 Set 和 WeakSet 的对比
| 特性 | Set | WeakSet | 
|---|---|---|
| 存储类型 | 可以存储任何类型(原始值或对象) | 只能存储对象 | 
| 引用方式 | 强引用,元素不会被垃圾回收 | 弱引用,元素会在没有其他引用时被垃圾回收 | 
| 迭代 | 支持迭代(forEach()、values() 等) | 不支持迭代操作(无法使用 forEach() 等) | 
| 内存管理 | 元素始终存在,直到手动删除 | 自动释放内存,当没有其他引用时会被垃圾回收 | 
| 应用场景 | 去重、集合运算、缓存、处理唯一值等 | 对象标记、内存管理、避免内存泄漏 | 
- 支持的数据类型:
Set可以存储任何类型的值,而WeakSet只能存储对象。 - 垃圾回收:
Set中的元素是强引用,不会被垃圾回收,而WeakSet中的元素是弱引用,能在没有其他引用时被自动回收。 - 是否支持遍历:
Set支持遍历,而WeakSet不支持遍历。这是因为WeakSet的元素是弱引用,不能保证它们会一直存在。 - 内存管理:
WeakSet用于管理对象的生命周期,适合用于标记和追踪对象而不会影响它们的垃圾回收。 
5.5 使用选择
- 使用 
Set当你需要存储任意类型的唯一值时,并且需要对这些值进行迭代和其他集合操作。 - 使用 
WeakSet当你需要存储对象的弱引用,并且不需要对这些对象进行迭代或操作时,特别是在避免内存泄漏的场景中。 
6. Map、WeakMap、Set、WeakSet总结
| 特性/集合类型 | Map | WeakMap | Set | WeakSet | 
|---|---|---|---|---|
| 存储数据 | 键值对(key-value) | 键值对(key-value),但键是弱引用 | 唯一值集合(无重复元素) | 唯一值集合(无重复元素),且值是对象 | 
| 键类型 | 可以是任意数据类型(原始值、对象、函数等) | 键必须是对象(弱引用) | 可以是任意数据类型(原始值、对象、函数等) | 只能是对象(弱引用) | 
| 值类型 | 可以是任意数据类型(原始值、对象、函数等) | 值可以是任意数据类型(原始值、对象、函数等) | 可以是任意数据类型(原始值、对象、函数等) | 可以是任意数据类型,但元素必须是对象 | 
| 垃圾回收 | 键和值都不会被垃圾回收机制自动清除 | 键是弱引用,只有当对象没有其他引用时才会被回收 | 不涉及垃圾回收,值保持直到手动删除 | 键是弱引用,且只有对象作为值,当对象没有其他引用时,会被垃圾回收 | 
| 大小 | 可通过 size 获取集合大小 | 无 size 属性,不能直接获取集合大小 | 可通过 size 获取集合大小 | 无 size 属性,不能直接获取集合大小 | 
| 遍历支持 | 支持遍历(forEach, for-of, keys(), values(), entries()) | 不支持遍历 | 支持遍历(forEach, for-of, values(), keys(), entries()) | 不支持遍历 | 
| 更新操作 | 支持更新键值对(set(),delete(),clear()) | 不支持更新键值对,只能 set() 新增键值对或 delete() 删除 | 支持添加、删除元素(add(),delete(),clear()) | 支持添加、删除元素(add(),delete(),clear()) | 
| 性能 | 查找性能优于普通对象,适合大量数据存储和快速查找 | 由于弱引用机制,适合处理需要垃圾回收的对象数据 | 查找性能较好,适用于去重操作 | 适合用于存储对象引用,避免内存泄漏 | 
| 用途场景 | 存储键值对,适合需要频繁更新和查找的场景 | 存储与对象相关的元数据,防止内存泄漏 | 存储唯一值,去重操作,高效查找 | 追踪对象引用,防止内存泄漏 | 
6.1 对比
相同点:
Map和WeakMap都是存储键值对的数据结构,而Set和WeakSet存储的是唯一的值。Set和WeakSet不允许元素重复;Map和WeakMap中的键是唯一的。WeakMap和WeakSet都是基于弱引用来处理数据,因此可以避免内存泄漏的问题。- 所有四种数据结构都支持 
delete()方法来删除特定元素。 
不同点:
- 键/值:
Map和WeakMap都存储键值对,Set和WeakSet只存储值。 - 数据类型限制:
WeakMap和WeakSet的键/值必须是对象,而Map和Set的元素可以是任何类型。 - 垃圾回收:
WeakMap和WeakSet利用弱引用机制,垃圾回收时会自动清理不再被引用的对象;而Map和Set没有这种机制。 - 遍历支持:
Map和Set都支持遍历操作(可以使用forEach或者for-of),但WeakMap和WeakSet由于使用弱引用,不支持遍历。 
6.2 应用场景
Map
- 缓存:适合用于存储键值对,尤其是当键可以是复杂对象或函数时。
 - 关联数组:需要根据特定键查找、更新或删除值时,
Map是一个优秀的选择。 - 数据存储与查询:例如用户设置、存储对象与属性映射等场景。
 
WeakMap
- 防止内存泄漏:当需要关联对象时(例如将附加数据存储在 DOM 元素上),
WeakMap可以避免内存泄漏,因为它会自动清理不再使用的键。 - 私有数据:可以通过 
WeakMap模拟私有属性,只能通过对象的引用访问。 
Set
- 去重:使用 
Set可以方便地去除数组中的重复元素。 - 集合运算:
Set可以用于表示数学中的集合,进行交集、并集和差集运算。 - 快速查找:当需要频繁检查某个值是否存在于集合中时,
Set提供了高效的查找操作。 
WeakSet
- 对象引用管理:用于管理对象引用,确保对象在不再使用时可以被垃圾回收。
 - 避免内存泄漏:适用于跟踪 DOM 元素或其他对象的引用,并在对象不再被引用时自动清理内存。
 - 资源回收:如 DOM 元素、事件监听器等,当对象不再使用时自动释放内存。
 
                                    
评论记录:
回复评论: