JS中的结构体Map(哈希)用法

好的!Map 是 ES6 引入的一种键值对数据结构,与传统的 Object 不同,它的键可以是任意类型(对象、函数、原始类型),且保留元素插入顺序。以下是核心用法和场景解析:


一、基本特性对比(Map vs Object)

特性MapObject
键的类型任意类型(包括对象)仅字符串或 Symbol
遍历顺序插入顺序无序(ES6后对象也有序但复杂)
性能频繁增删时更优静态键值对时略快
序列化无法直接 JSON.stringify支持
默认键有原型链可能带来冲突键

二、Map 核心用法

1. 初始化与增删改查
// 初始化
const map = new Map();

// 添加键值对(键可以是对象、函数等)
const keyObj = { id: 1 };
map.set('name', 'Alice');      // 字符串键
map.set(keyObj, 'Value1');     // 对象键
map.set(100, 'Century');       // 数字键

// 获取值
console.log(map.get('name'));  // 'Alice'
console.log(map.get(keyObj));  // 'Value1'

// 判断键存在性
console.log(map.has(100));     // true

// 删除键
map.delete('name');

// 清空
// map.clear();

// 大小
console.log(map.size);         // 2
2. 遍历方法
const map = new Map([
  ['a', 1],
  ['b', 2]
]);

// for...of 遍历
for (const [key, value] of map) {
  console.log(key, value); // 'a' 1, 'b' 2
}

// forEach 遍历
map.forEach((value, key) => {
  console.log(key, value);
});

// 获取键、值、条目集合
console.log([...map.keys()]);   // ['a', 'b']
console.log([...map.values()]); // [1, 2]
console.log([...map.entries()]); // [['a', 1], ['b', 2]]

三、高级用法场景

1. 用对象作为键(避免引用泄漏)
const user1 = { id: 1 }, user2 = { id: 2 };
const permissions = new Map();

permissions.set(user1, ['read', 'write']);
permissions.set(user2, ['read']);

console.log(permissions.get(user1)); // ['read', 'write']
2. 存储函数元数据
const funcRegistry = new Map();
const func = () => console.log('Hello');

funcRegistry.set(func, {
  author: 'Alice',
  version: '1.0'
});

console.log(funcRegistry.get(func).author); // 'Alice'
3. 缓存计算结果(Memoization)
const cache = new Map();

function computeExpensiveValue(key) {
  if (cache.has(key)) {
    return cache.get(key);
  }
  const result = /* 复杂计算 */ key.toUpperCase();
  cache.set(key, result);
  return result;
}

四、与 Object/Array 转换

1. Map ↔ 二维数组
// Map → 数组
const map = new Map([['a', 1], ['b', 2]]);
const arr = Array.from(map); // [['a', 1], ['b', 2]]

// 数组 → Map
const newMap = new Map(arr);
2. Map → Object(键需为字符串)
const map = new Map([['name', 'Bob'], [Symbol(), 'secret']]);
const obj = Object.fromEntries(map);
console.log(obj); // { name: 'Bob' } (Symbol键被忽略)

五、性能优化场景

1. 高频增删键值对
// 使用 Map 更高效
const dynamicKeys = new Map();
for (let i = 0; i < 1000; i++) {
  dynamicKeys.set(i, Math.random());
}
dynamicKeys.delete(500); // 比 delete object[key] 更快
2. 避免键冲突
// 使用 Map 避免原型链污染
const safeMap = new Map();
safeMap.set('toString', 'customValue'); // 安全

const obj = {};
obj['toString'] = 'customValue'; // 覆盖原型方法,引发意外行为

六、注意事项

  • 内存管理:如果键是对象,Map 会强引用该对象,可能导致内存泄漏(需手动删除或使用 WeakMap)。
  • 类型严格map.get(1)map.get('1') 视为不同键。
  • 迭代消耗:频繁遍历时优先用 for...of 而非 forEach

如果需要更专业的应用场景(如与 WeakMap 对比)或具体编程问题,可以继续提问! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值