一、Map 的基本原理
Map 是 JavaScript 中的一种数据结构,它提供了一种键值对的存储方式。与普通的对象相比,Map 具有以下特点:
-
键可以是任意类型(包括对象)
-
键是唯一的
-
保持插入顺序
-
可以轻松获取大小(通过 size 属性)
-
提供了丰富的操作方法
基本使用示例:
const map = new Map();map.set('key1', 'value1');map.set('key2', 'value2');console.log(map.get('key1')); // 'value1'console.log(map.size); // 2
二、Map 的 size 属性详解
Map 的 size 属性表示 Map 中键值对的数量,而不是字节大小。它与 Buffer 没有直接关系。
size 的含义:
-
size表示Map中键值对的数量 -
每次调用
set()方法添加新的键值对时,size会增加 -
每次调用
delete()方法删除键值对时,size会减少 -
调用
clear()方法时,size会变为0
与 Buffer 的区别:
-
Buffer用于处理二进制数据,length属性表示字节数 -
Map的size只表示键值对的数量 -
如果需要计算
Map占用的内存大小,需要手动计算每个键值对的大小
计算 Map 实际内存占用的方法:
function getMapMemorySize(map) { let totalSize = 0; map.forEach((value, key) => { // 计算键的大小 if (typeof key === 'string') { totalSize += Buffer.byteLength(key); } elseif (key instanceof Buffer) { totalSize += key.length; } // 计算值的大小 if (typeof value === 'string') { totalSize += Buffer.byteLength(value); } elseif (value instanceof Buffer) { totalSize += value.length; } elseif (typeof value === 'object') { totalSize += Buffer.byteLength(JSON.stringify(value)); } }); return totalSize;}
之前看组员编写代码时就未考虑键的大小计算,这里需要注意下!
注意事项:
-
Map的size属性是实时的,会随着Map的变化而更新 -
size属性是只读的,不能直接修改 -
如果需要限制
Map的大小,需要手动实现
二、Map 的 forEach 遍历
Map 提供了 forEach 方法用于遍历,其语法为:
map.forEach((value, key, map) => { // 处理逻辑});
这里有一个看似反直的设计:参数顺序是 (value, key),而不是 (key, value)。这种设计的原因在于:
-
保持一致性:
所有集合类型的
forEach的第一个参数都是值,保持了API的一致性。
-
Array的forEach是(value, index, array) -
Set的forEach是(value, value, set) -
Map的forEach是(value, key, map)
- 使用频率:
-
在遍历时,通常更关注值而不是键
-
把值放在第一个参数位置可以让代码更简洁
三、Map 的其他遍历方法
除了 forEach,Map 还提供了多种遍历方式:
for...of 遍历 entries():
for (const [key, value] of map.entries()) { console.log(key, value);}
for...of 遍历 keys():
for (const key of map.keys()) { console.log(key);}
for...of 遍历 values():
for (const value of map.values()) { console.log(value);}
直接遍历 Map(等同于 entries()):
for (const [key, value] of map) { console.log(key, value);}
四、Map 的应用场景
Map 在以下场景中特别有用:
- 缓存系统:
-
使用
Map存储缓存数据 -
键可以是复杂的对象
-
可以轻松管理缓存大小
- 数据映射:
-
需要将一种数据映射到另一种数据
-
保持数据的对应关系
- 对象关联:
-
当需要将对象作为键时
-
普通对象只能使用字符串作为键
- 频率统计:
-
统计元素出现次数
-
快速查找和更新
- 配置管理:
-
存储配置信息
-
支持动态更新
五、Map 与 Object 的比较
特性
Map
Object
键的类型
任意类型
字符串或 Symbol
键的顺序
保持插入顺序
不保证顺序
大小获取
size
属性
需要手动计算
性能
频繁增删时更好
少量数据时更好
序列化
需要特殊处理
直接支持 JSON
六、最佳实践建议
-
当键是字符串时,优先使用 Object
-
当需要非字符串键时,使用 Map
-
需要频繁增删操作时,使用 Map
-
需要保持插入顺序时,使用 Map
-
需要统计大小时,使用 Map