首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-11-26 09:05
  • 2213
  • 10406
juejin.cn

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 的区别

特性MapWeakMap
键的类型可以是任何类型(包括对象、函数等)键必须是对象类型
垃圾回收键值对不会被垃圾回收机制影响键是弱引用,可以被垃圾回收
支持迭代支持 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 常用方法

  1. add(value):向 Set 中添加一个元素。如果该元素已存在,Set 会忽略它。
js
代码解读
复制代码
let set = new Set(); set.add(1); set.add(2); set.add(1); // 不会添加,重复的元素会被忽略 console.log(set); // Set { 1, 2 }
  1. has(value):检查 Set 中是否包含指定的元素。
js
代码解读
复制代码
console.log(set.has(1)); // true console.log(set.has(3)); // false
  1. delete(value):删除 Set 中的指定元素。
js
代码解读
复制代码
set.delete(1); console.log(set); // Set { 2 }
  1. clear():清空 Set 中的所有元素。
js
代码解读
复制代码
set.clear(); console.log(set); // Set {}
  1. size:返回 Set 中元素的数量。
js
代码解读
复制代码
console.log(set.size); // 2
  1. forEach(callback):对 Set 中的每个元素执行一个回调函数。
js
代码解读
复制代码
set.forEach(value => console.log(value)); // 输出 1 和 2
  1. 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 常用方法

  1. add(value):向 WeakSet 中添加一个对象。元素必须是对象类型。
ini
代码解读
复制代码
let ws = new WeakSet(); let obj = {}; ws.add(obj);
  1. has(value):检查 WeakSet 中是否包含指定的对象。
arduino
代码解读
复制代码
console.log(ws.has(obj)); // true
  1. 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 的对比

特性SetWeakSet
存储类型可以存储任何类型(原始值或对象)只能存储对象
引用方式强引用,元素不会被垃圾回收弱引用,元素会在没有其他引用时被垃圾回收
迭代支持迭代(forEach()、values() 等)不支持迭代操作(无法使用 forEach() 等)
内存管理元素始终存在,直到手动删除自动释放内存,当没有其他引用时会被垃圾回收
应用场景去重、集合运算、缓存、处理唯一值等对象标记、内存管理、避免内存泄漏
  • 支持的数据类型:Set 可以存储任何类型的值,而 WeakSet 只能存储对象。
  • 垃圾回收:Set 中的元素是强引用,不会被垃圾回收,而 WeakSet 中的元素是弱引用,能在没有其他引用时被自动回收。
  • 是否支持遍历:Set 支持遍历,而 WeakSet 不支持遍历。这是因为 WeakSet 的元素是弱引用,不能保证它们会一直存在。
  • 内存管理:WeakSet 用于管理对象的生命周期,适合用于标记和追踪对象而不会影响它们的垃圾回收。

5.5 使用选择

  • 使用 Set 当你需要存储任意类型的唯一值时,并且需要对这些值进行迭代和其他集合操作。
  • 使用 WeakSet 当你需要存储对象的弱引用,并且不需要对这些对象进行迭代或操作时,特别是在避免内存泄漏的场景中。

6. Map、WeakMap、Set、WeakSet总结

特性/集合类型MapWeakMapSetWeakSet
存储数据键值对(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 元素、事件监听器等,当对象不再使用时自动释放内存。
注:本文转载自juejin.cn的温暖前端的文章"https://juejin.cn/post/7440819804427878440"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

104
前端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top