Map、Set和WeakMap、WeakSet粗略讲解。

164 阅读3分钟

1.Map(映射)

是什么:

  • 键值对集合,键可以是任何对象(对象、原始值)
  • 保持插入顺序

特点:

const map = new Map();
map.set('name', 'John'); // 键是字符串
map.set(1, 'number key');// 键是数字
const objKey = {};
map.set(objKey, 'object key'); // 键是对象

常用方法:

基本操作方法:

1.set(key, value)-向Map中添加或更新键值对
map.set('name', 'Alice');
map.set(1, 'number key');
2.get(key)-获取指定键对应的值,如果不存在则返回undefined
map.get('name'); // 'Alice'
map.get('nonexistent'); // undefined
3.has(key)-检查Map中是否存在指定的键
map.has('name'); // true
map.has('age'); // false
4.delete(key)-删除对应的键值对,返回布尔值表示是否删除成功
map.delete('name'); // true
map.delete('age'); // false
5.clear()-清空所有键值对
map.clear();

遍历方法:

6.keys()-返回Map中所有键的迭代器
for (let key of map.keys()) {
    console.log(key);
}
7.values()-返回Map中所有值的迭代器
for (let value of map.values()) {
    console.log(value);
}
8.entries()-返回Map中所有键值对的迭代器
for (let [key, value] of map.entries()) {
    console.log(key, value)
}
// 等同于
for (let [key, value] of map) {
    console.log(key, value)
}
9.forEach(callBackFn, [thisArg])-对Map中每个键值对执行回调函数
map.forEach((value, key)) => {
    console.log(key, value)
}

属性

10.size-获取Map中键值对的数量
consoe.log(map.size);

与Object的区别:

  • Map的键可以是任意类型,Object的键只能是String和Symbol
  • Map有size属性直接获取元素数量
  • Map保持插入顺序
  • 性能更好(频繁增删的场景)

2.Set(集合)

是什么:

  • 值唯一的集合(类似数组,但成员唯一)
  • 保持插入顺序

特点:

const set = new Set();
set.add(1);
set.add('text');
set.add({}); // 对象引用独立
set.add(1); // 不会重复添加

基本操作方法

1.add(value)-向Set中添加一个新值,返回Set对象本身(支持链式调用)
set.add(1);
set.add(2).add(3); // 链式调用
2.has(value)-检查Set中是否存在指定的值
set.has(1); // true
set.has(4); // false
3.delete(value)-删除指定的值,返回布尔值表示是否删除成功
set.delete(1); // true
set.delete(4); // false
4.clear()-清空set中所有的值
set.clear();

遍历方法

5.keys()-返回set中所有值的迭代器(与values()相同)
for (let item of set.keys()) {
    console.log(item);
}
6.values()-返回所有值的迭代器
7.entries()-与values()和keys()相同,为了和Map保持一致
8.forEach(callBackFn, [thisArg])-对Set中每个值执行回调函数
set.forEach(value) => {
    console.log(value);
}

属性

size-获取Set中值的数量(属性,不是方法)

Set的特殊用途

[...new Set(array)] // 数组去重
new Set([...setA, ...setB]) // 并集
new Set([...setA]).filter(x => setB.hax(x))) // 交集
new Set([...setA]).filter(x => !setB.has(x))) // 差集

3.WeakMap(弱映射)

是什么:

  • 键必须是对象的弱引用Map
  • 不可遍历(没有size, keys()方法)

特点:

const wm = new WeakMap();
let obj = {};
vm.set(obj, 'private data');
obj = null; // 当obj被GC回收时,WeakMap中的条目自动移除

要点:

  • 典型用途:存储私有数据、DOM节点元数据

与Map的关键区别:

  • 键是弱引用(不阻止垃圾回收)
  • 不可枚举
  • 没有size属性

4.WeakSet(弱集合)

是什么:

  • 值必须是对象的弱引用Set
  • 不可遍历

特点:

const ws = new WeakSet();
let obj = {};
ws.add(obj);
console.log(ws.has(obj)); // true
obj = null; // 当obj被GC回收时,自动从WeakSet中移除

要点:

  • 典型用途:标记对象,如已经用过的对象

与Set的关键区别

  • 值必须是对象
  • 弱引用,不阻止垃圾回收
  • 不可枚举

5.常见问题

1.Map和Object如何选择?

  • 需要非字符串键或保持插入顺序时使用Map
  • 只需要简单键值对且键是字符串时用Object

2.WeakMap为什么不能遍历?

  • 因为弱引用特性,随时可能被垃圾回收机制处理,遍历结果不靠谱

3. Set如何实现数组去重?

  • const newArray = [...new Set(array)]

4.为什么WeakMap/WeakSet的值/键必须是对象?

  • 因为只有对象才能被垃圾回收机制管理,原始值不受GC的影响