Map
Map 用于存储键值对。
-
添加属性:
使用 Map 的set()
方法可以向 Map 对象中添加键值对。例如:const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2');
通过二维数组快速创建 map 键值对。
let arr = [ [1, 2], [2, 3], [3, 4] ] let map = new Map(arr) console.log(map) // Map(3) { 1 => 2, 2 => 3, 3 => 4 }
map.keys() // MapIterator { 1, 2, 3 } map.entries() // MapIterator { 1 => 2, 2 => 3, 3 => 4 } map.values() // MapIterator { 2, 3, 4 }
-
获取属性和长度:
使用 Map 的get()
方法可以根据键获取对应的值。使用 Map 的size
属性可以获取 Map 对象中键值对的数量。例如:const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2'); const value1 = map.get('key1'); // 获取键为 'key1' 的值 const size = map.size; // 获取 Map 对象中键值对的数量
let obj = { a: 1, b: 2, c: 3 } console.log(Object.keys(obj).length)
-
遍历 Map 对象:
使用 Map 的forEach()
方法可以遍历 Map 对象的键值对。可以传入一个回调函数,对每个键值对执行相应的操作。例如:const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2'); map.forEach((value, key) => { console.log(key, value); // 打印每个键值对 });
console.log(map) // Map(3) { 1 => 2, 2 => 3, 3 => 4 } for (let mapElement of map) { console.log(mapElement) // [ 1, 2 ] // [ 2, 3 ] // [ 3, 4 ] }
-
删除属性:
使用 Map 的delete()
方法可以根据键删除对应的键值对。例如:const map = new Map(); map.set('key1', 'value1'); map.set('key2', 'value2'); map.delete('key1'); // 删除键为 'key1' 的键值对
-
Map 和 Object 的区别:
- 额外的键:Map 默认情况下不包含任何键,只包含插入的键;一个 Object 有一个原型,原型链上的键名可能和自己在对象上设置的键名冲突,可以使用 Object.create(null) 创建一个没有原型的对象
- 键的类型:Map 的键可以使用任意类型的值,包括对象、函数、NaN 等,而 Object 的键只能是 String 或 Symbol 类型。
- 插入顺序:Map 会按照插入顺序保存键值对,而 Object 并不保证属性的顺序(无序)。
- 迭代和大小:Map 提供了内置的迭代器和方便的方法来获取大小(使用
size
属性),而 Object 需要手动处理迭代和计算大小。 - 性能:在需要频繁添加、删除和查找键值对的场景中,Map 的性能通常优于 Object。
WeakMap
和 Map 很相似,但会有一些差异:
-
引用关联和垃圾回收:WeakMap中的键是弱引用,而Map中的键是强引用。当对象(键)被垃圾回收时, Map 对象将保持引用链接,而 WeakMap 对象将丢失链接。
-
键类型限制:在Map中,键可以是任意类型的值,包括原始类型和对象。而在WeakMap中,键只能是对象类型。这是因为WeakMap的实现依赖于对象的引用。
-
迭代和大小:Map提供了迭代方法,如forEach、keys、values和entries,可以遍历Map中的键值对。而WeakMap没有提供直接的迭代方法,也没有办法获取WeakMap的大小(即键值对的数量)。
-
并非 Map 中所有方法都支持。WeakMap 支持的方法:delete、get、has、set。
-
性能:由于WeakMap中的键是弱引用,它的性能可能会受到一些限制。在大规模操作时,WeakMap的性能可能会比Map略差。此外,由于WeakMap不会保留对象的引用,它对垃圾回收的支持更好,有助于避免内存泄漏。
Set
Set 允许存储唯一的值,无论是原始值还是对象引用。
-
添加元素:
- 使用
add(value)
方法向 Set 中添加元素。和 Map 一样,也是不允许添加重复值。如果该值已经存在于 Set 中,则不会重复添加。
- 使用
-
遍历集合:
- Set 没有提供直接访问元素的索引,因此无法通过索引来遍历。但可以使用迭代器来遍历 Set 中的元素。
- 使用
forEach(callbackFn, thisArg)
方法迭代 Set 中的每个元素,其中callbackFn
是回调函数,thisArg
是可选的上下文对象。 - 使用
for...of
循环遍历 Set 中的元素。
-
删除元素:
- 使用
delete(value)
方法从 Set 中删除指定的元素。如果成功删除该元素,返回true
;如果元素不存在,则返回false
。 - 使用
clear()
方法可以清空整个 Set。
- 使用
-
应用场景:
- 去重:Set 中的元素是唯一的,这使得它成为去除数组中重复元素的有效工具。
let arr = [1,3,3,4,5,6,6,6] let unique = [...new Set(arr)] console.log(unique)
- 并集、交集、差集
const setA = new Set([1, 2, 3, 4]); const setB = new Set([3, 4, 5, 6]); // 交集 const intersection = new Set([...setA].filter(x => setB.has(x))); console.log([...intersection]); // 输出: [3, 4] // 差集 const difference = new Set([...setA].filter(x => !setB.has(x))); console.log([...difference]); // 输出: [1, 2] // 并集 const union = new Set([...setA, ...setB]); console.log([...union]); // 输出: [1, 2, 3, 4, 5, 6]
需要注意的是,Set 中的元素是根据其值的唯一性进行存储和比较的,因此对于对象类型的值,它们在 Set 中被视为引用而不是值本身。这意味着两个具有相同属性和值的不同对象将被视为两个不同的元素。
以下是使用 Set 的示例代码:
const set = new Set();
set.add(1);
set.add(2);
set.add(3);
console.log(set.size); // 输出: 3
set.forEach((value) => {
console.log(value);
});
// 输出:
// 1
// 2
// 3
set.delete(2);
console.log(set.has(2)); // 输出: false
set.clear();
console.log(set.size); // 输出: 0
WeakSet
WeakSet 和 Set 区别如下:
- WeakSet 只能储存对象引用,不能存放值,而 Set 对象都可以
- WeakSet 对象中储存的对象值都是被弱引用的,即垃圾回收机制不考虑 WeakSet 对该对象的引用,如果没有其他的变量或者属性引用这个对象值,则这个对象将会被垃圾回收掉。(不考虑该对象还存在于 WeakSet
中),所以 WeakSet 对象里有多少个成员元素,取决于垃圾回收机制有没有运行,运行前后成员个数可能不
一致,遍历结束之后,有的成员可能取不到,被垃圾回收了。因此ES6规定,WeakSet对象是无法被遍历的,
也没有办法拿到它包含的所有元素。
WeakSet 能够使用的方法如下:add(), delete(), has(), clear()
如果被垃圾回收掉,WeakSet 将丢失对内部数据的访问链接。