JavaScript中的Map类

在 JavaScript 中,Map 是 ES6(ECMAScript 2015)引入的一种全新的数据结构,用于存储键值对(key-value pairs)

专门用来解决传统对象({})无法用非字符串 / 非 Symbol 类型作为键、键会被隐式转换、无法获取键值对数量等痛点。

一、为什么需要 Map?与 Object 的对比

在使用 Map 之前,开发者通常用普通对象 {} 来存储键值对,但对象存在以下局限:
表格
 
特性 Object Map
键的类型 只能是字符串或 Symbol 任意类型(对象、函数、数字、布尔值等)
键值对数量 需手动计算(Object.keys().length 直接通过 .size 获取
遍历顺序 ES2015 前不保证,之后按插入顺序(但语义不清晰) 严格保证插入顺序
原型干扰 可能继承原型链上的属性(如 toString 无原型污染,纯净的键值对集合
性能 频繁增删时性能较差 针对增删优化,大数据量下性能更优
序列化 可直接 JSON.stringify 需手动转换(如转为数组或对象)

结论:当你需要非字符串键、频繁操作、或明确需要有序集合时,优先使用 Map。 

二、Map 的基本用法

1. 创建 Map

// 空 Map
const map = new Map();

// 初始化时传入二维数组
const userMap = new Map([
  ['name', '小明'],
  ['年龄',18 ], // 数字键
  ['是学生',true] // 布尔键
]);
Myname = userMap.get('name');
console.log(Myname)

MyAge = userMap.get('年龄');
console.log(MyAge)

MyStudent = userMap.get('是学生')
console.log(MyStudent)

运行结果如下:

image

2. 核心 API

方法 说明 示例
set(key, value) 添加或更新键值对,支持链式调用 map.set('a', 1).set('b', 2)
get(key) 获取指定键的值,不存在返回 undefined map.get('a')
has(key) 判断是否存在某键 map.has('a') // true
delete(key) 删除指定键,返回是否删除成功 map.delete('a')
clear() 清空所有键值对 map.clear()
size 属性,返回键值对数量 map.size
map.entries() [key, value] (数组) 需要同时处理键和值时(默认遍历方式)

2.1 基本用法

const map = new Map();

map.set('name', 'Bob');
map.set(100, 'number-key');
map.set({ id: 1 }, 'object-key');

console.log(map.get('name'));        // "Bob"
console.log(map.get(100));           // "number-key"
console.log(map.has({ id: 1 }));     // false!(不同对象引用)
console.log(map.size);               // 3

const objKey = { id: 1 };
map.set(objKey, 'same-object-key');
console.log(map.has(objKey));        // true(相同引用)

console.log(map.size)       // 4

map.clear()     // 清空
console.log(map.size);        // 0

⚠️ 注意:对象作为键时,比较的是引用地址,而非内容。两个内容相同但不同的对象被视为不同的键。

运行结果如下:

image

2.2 map.entries()用法

map.entries() 是 JavaScript Map 对象的一个方法,用于返回一个新的迭代器(Iterator)对象。这个迭代器包含了 Map 中所有键值对的数组,格式为 [key, value]
它是 Map 遍历的核心机制之一,也是 for...of 循环默认调用的方法。
 
 基本用法与返回值 ,如下:
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

const iterator = map.entries();

console.log(iterator); 
// 输出: MapIterator { [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] }
运行结果如下:
image 
HTML中输出结果如下:
image
  • 返回值:一个 Map Iterator 对象。
  • 内容格式:每次迭代产出一个包含两个元素的数组 [key, value]
  • 顺序:严格按照插入顺序排列。

配合 for...of 循环(最常用)可以直接解构出 keyvalue,代码如下所示:

const map = new Map([
  ['name', 'Alice'],
  ['age', 25],
  ['role', 'Admin']
]);

for (const [key, value] of map.entries()) {
  console.log(`${key}: ${value}`);
}
// 输出:
// name: Alice
// age: 25
// role: Admin

运行结果如下:

image

💡 小知识:如果你直接写 for (const [key, value] of map),其实底层自动调用的就是 map.entries()。所以以下两行代码效果完全一样:

for (const [k, v] of map) { ... }       // 简写
for (const [k, v] of map.entries()) { ... } // 显式调用

如果你想把 Map 的所有键值对一次性变成一个二维数组,可以使用扩展运算符 ...Array.from()

const entriesArray = [...map.entries()];
// 结果: [ ['name', 'Alice'], ['age', 25], ['role', 'Admin'] ]

// 或者
const entriesArray2 = Array.from(map.entries());

三、遍历 Map

Map 是可迭代对象,支持多种遍历方式,且默认按插入顺序

1. for...of 遍历

const map = new Map([['a', 1], ['b', 2]]);

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

// 只遍历键
for (const key of map.keys()) {
    console.log(key);       // a b
}

// 只遍历值
for (const value of map.values()) {
    console.log( value);        // 1 2
}

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

运行结果如下:

image

 

2. forEach 方法

// // 空 Map
// const map = new Map();
//
// // 初始化时传入二维数组
// const userMap = new Map([
//   ['name', '小明'],
//   ['年龄',18 ], // 数字键
//   ['是学生',true] // 布尔键
// ]);
// Myname = userMap.get('name');
// console.log(Myname)
//
// MyAge = userMap.get('年龄');
// console.log(MyAge)
//
// MyStudent = userMap.get('是学生')
// console.log(MyStudent)

// const map = new Map();
//
// map.set('name', 'Bob');
// map.set(100, 'number-key');
// map.set({ id: 1 }, 'object-key');
//
// console.log(map.get('name'));        // "Bob"
// console.log(map.get(100));           // "number-key"
// console.log(map.has({ id: 1 }));     // false!(不同对象引用)
// console.log(map.size);               // 3
//
// const objKey = { id: 1 };
// map.set(objKey, 'same-object-key');
// console.log(map.has(objKey));        // true(相同引用)
//
// console.log(map.size)       // 4
//
// map.clear()     // 清空
// console.log(map.size);        // 0

const map = new Map([['a', 1], ['b', 2]]);

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

// 只遍历键
for (const key of map.keys()) {
    console.log(key);       // a b
}

// 只遍历值
for (const value of map.values()) {
    console.log( value);        // 1 2
}

// 遍历键值对
for (const [key, value] of map.entries()) {
    console.log(key, value);        // a 1 b 2
}
// 分隔线
console.log("-----------------")
// forEach的用法
map.forEach((value, key) => {
  console.log(key, value);
});

运行结果如下:

image 

 

四、Map 与普通对象({})的区别

关键区别示例

// 对象:数字键会被转成字符串
const obj = {};
obj[1] = '这是“对象”';
console.log(obj['1']); //  (键被隐式转换)

// Map:数字键和字符串键是两个不同键
const map = new Map();
map.set(1, '这是“Map类”');
console.log(map.get(1)); // 
console.log(map.get('1')); // 输出“undefined” ✔ 不混淆

运行结果如下:

image 

 

五、高级用法

1. 对象作为键(Map 最强特性)

const user1 = { name: '张三' };
const user2 = { name: '李四' };

const map = new Map();
map.set(user1, '管理员');
map.set(user2, '普通用户');

console.log(map.get(user1));; // '管理员'

运行结果如下:

image 

2. Map ↔ 对象 互转

// Map → 对象(要求 Map 的键必须是字符串/Symbol)
const map = new Map([['a', 1], ['b', 2]]);
const obj = Object.fromEntries(map);
console.log(obj)

// 对象 → Map
const obj2 = { a: 1, b: 2 };
const map2 = new Map(Object.entries(obj2));
console.log(map2)

运行结果如下:

image 

2. Map ↔ 数组 互转

 

const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

const arr = Array.from(map);
console.log(arr)
// 结果:[['a',1], ['b',2], ['c',3]]

// 或用扩展运算符:
const arr2 = [...map];
console.log(arr2)

运行结果如下:

image 

六、注意事项

  1. 引用类型键必须是同一个引用
const map = new Map();
map.set({}, '空对象');
console.log(map.get({})); // undefined !!! 两个 {} 不是同一个对象

运行结果如下:

image

Map 是引用类型,赋值是传引用,不是深拷贝 

   2.new Map(iterable) 对参数的唯一要求

      new Map(iterable) 对参数的唯一要求是:
  1. 必须是可迭代的(拥有 Symbol.iterator 方法,能被 for...of 遍历)。
  2. 遍历出的每一项必须是一个包含两个元素的序列(第一项作为 key,第二项作为 value)。
如果传入的数据不符合这两点(例如传入一个普通对象 { a: 1 } 或者一维数组 ['a', 'b']),程序会报错

❌ 错误示范

  

// 错误 1: 传入普通对象 (对象默认不可迭代)
new Map({ a: 1, b: 2 }); 
// TypeError: object is not iterable

// 错误 2: 传入一维数组 (迭代出来的是单个字符/元素,不是 [key, value] 对)
new Map(['a', 'b']); 
// TypeError: Iterator result undefined is not an object (或者类似的解构错误)

 

 

 

 

 

 

posted @ 2026-03-24 21:02  chenlight  阅读(5)  评论(0)    收藏  举报