Map
[TOC]
索引
构造方法:
- new Map():
(iterable?)
,用于创建一个新的 Map 对象的构造函数。暂时没有字面量创建方式。
方法:
- map.set():
(key, value)
,修改原集合,用于添加或更新键值对。 - map.get():
(key)
,用于根据键获取对应的值。 - map.has():
(key)
,用于检查指定键是否存在于 Map 中。 - map.delete():
(key)
,修改原集合,用于从 Map 中删除指定的键值对。 - map.clear():
()
,修改原集合,用于完全清空 Map 中的所有键值对。 - map.forEach():
(callbackFn, thisArg?)
,用于按插入顺序遍历 Map 的所有键值对并执行回调函数。
Map
构造方法
new Map()@
new Map():(iterable?)
,用于创建一个新的 Map 对象的构造函数。暂时没有字面量创建方式。
- iterable?:
Iterator
,接受一个包含键值对数组的迭代器(如数组、Set、Map 等)。 - 返回:
- map:
Map
,返回一个新的 Map 对象;不传参数返回一个空 Map。
核心特性:
可迭代对象的详细要求:
- 必须提供 二元数组(长度为 2 的数组) 的集合
- 每个子数组格式:
[key, value]
jsconst validMap = new Map([ [new Date(), '日志'], [document.body, 'DOM 节点'], [10n, 'BigInt 键'] ]);
键值对初始化规则:
键唯一性:重复键会覆盖前值
jsconst map = new Map([ ['name', 'Alice'], ['name', 'Bob'] // 覆盖 'Alice' ]); console.log(map.get('name')); // 'Bob'
键类型自由:支持任意类型(对象、函数等)
jsconst objKey = {}; const map = new Map([ [objKey, '对象键'], [function() {}, '函数键'], [new Date(), '日期键'] ]);
引用类型键:内容相同的不同对象视为不同键
jsconst map = new Map([ [{id: 1}, 'A'], [{id: 1}, 'B'] // 两个独立对象,不会覆盖 ]); console.log(map.size); // 2
方法
set()@
map.set():(key, value)
,修改原集合,用于添加或更新键值对。
key:
any
,键值对的键。可以是原始值、对象、函数、NaN
等任何 JS 类型。value:
any
,与键关联的值。允许undefined
/null
等所有类型。返回:
map:
Map
,返回更新后的 Map 对象本身,支持链式调用。
核心特性:
添加新键值对:
当键不存在时,添加新条目:
jsconst map = new Map(); map.set('name', 'Alice'); // 添加新条目 console.log(map.size); // 1
更新现有值:
当键已存在时,更新其值:
jsmap.set('name', 'Bob'); // 更新值 console.log(map.get('name')); // 'Bob'
键比较规则:使用 "SameValueZero" 算法:
NaN
被视为相同键(尽管NaN !== NaN
)jsmap.set(NaN, 'First'); map.set(NaN, 'Override'); // 覆盖前值 console.log(map.get(NaN)); // 'Override'
引用类型按内存地址区分:
jsmap.set({}, 'A'); map.set({}, 'B'); // 不同对象,新增条目 console.log(map.size); // 2
链式调用:
利用返回值实现连续操作:
jsconst map = new Map(); map.set('a', 1) .set('b', 2) // 链式调用 .set('c', 3); console.log(map.size); // 3
Map 作为自身键:
允许但不推荐,易导致递归问题。
jsmap.set(map, '自引用键'); console.log(map.get(map)); // '自引用键'
示例:
基本使用:
jsconst configMap = new Map(); // 1. 添加配置 configMap.set('theme', 'dark') .set('fontSize', 16) .set('notifications', true); // 2. 更新配置 configMap.set('theme', 'light'); // 3. 使用对象键 const user = { id: 123 }; configMap.set(user, { permissions: ['read', 'write'] }); // 4. 获取值 console.log(configMap.get('fontSize')); // 16 console.log(configMap.get(user).permissions); // ['read','write'] // 5. 遍历 configMap.forEach((value, key) => { console.log(`${String(key)}: ${JSON.stringify(value)}`); });
get()@
map.get():(key)
,用于根据键获取对应的值。
key:
any
,要查找的键。可以是原始值、对象、函数、NaN
等任何 JS 类型。返回:
value:
any|undefined
,键存在返回对应的值;键不存在返回undefined
(不会抛出错误)。
核心特性:
键查找机制:使用 SameValueZero 算法:
NaN
被视为相同的键(即使NaN !== NaN
)jsmap.set(NaN, '特殊值'); console.log(map.get(NaN)); // '特殊值' console.log(map.get(0/0)); // '特殊值' (0/0 = NaN)
-0
和+0
被视为相同键jsmap.set(-0, '零值'); console.log(map.get(+0)); // '零值'
引用类型按内存地址区分:
jsconst obj1 = { id: 1 }; const obj2 = { id: 1 }; map.set(obj1, 'A'); console.log(map.get(obj1)); // 'A' console.log(map.get(obj2)); // undefined(不同对象)
示例:
不同类型原始值键:
jsconst userMap = new Map(); // 添加不同类型键 userMap.set('name', 'Alice'); userMap.set(101, { id: 101, role: 'admin' }); userMap.set(null, '空键值'); userMap.set(NaN, '非数值'); // 获取值 console.log(userMap.get('name')); // "Alice" console.log(userMap.get(101)); // {id: 101, role: 'admin'} console.log(userMap.get(null)); // "空键值" console.log(userMap.get(NaN)); // "非数值"
对象键:
js// 对象键示例 const alice = { name: 'Alice' }; userMap.set(alice, 'Alice对象'); console.log(userMap.get(alice)); // "Alice对象" console.log(userMap.get({ name: 'Alice' })); // undefined(不同对象)
链式调用:
js// 链式调用结合 const value = userMap .set('newKey', '临时值') .get('newKey'); console.log(value); // "临时值"
安全访问:
js// 安全访问示例 const userId = 102; const userData = userMap.get(userId) || { role: 'guest' }; console.log(userData.role); // "guest"(键不存在时使用默认值)
has()
map.has():(key)
,用于检查指定键是否存在于 Map 中。
key:
any
,要检查的键。可以是原始值、对象、函数、NaN
等任何 JS 类型。返回:
has:
boolean
,返回键是否存在(不会抛出错误)。
核心特性:
- 键查找机制:使用 SameValueZero 算法:
NaN
被视为相同的键(即使NaN !== NaN
)-0
和+0
被视为相同键- 引用类型按内存地址区分
示例:
基本使用:
jsconst config = new Map(); // 添加配置项 config.set('darkMode', true); config.set(NaN, '特殊配置'); config.set(null, '空键配置'); // 对象键示例 const user = { id: 101 }; config.set(user, { permissions: ['read'] }); // 检查键是否存在 console.log(config.has('darkMode')); // true console.log(config.has('lightMode')); // false console.log(config.has(NaN)); // true console.log(config.has(null)); // true // 检查对象键 console.log(config.has(user)); // true console.log(config.has({ id: 101 })); // false(不同对象)
安全操作模式:
js// 安全操作模式 function toggleDarkMode(map) { if (map.has('darkMode')) { const current = map.get('darkMode'); map.set('darkMode', !current); } else { map.set('darkMode', false); } }
检查前初始化:
js// 检查前初始化 const requiredKeys = ['apiUrl', 'timeout']; requiredKeys.forEach(key => { if (!config.has(key)) { config.set(key, getDefaultValue(key)); } });
链式操作(结合set):
js// 链式操作(结合set) config.has('debug') || config.set('debug', false);
delete()
map.delete():(key)
,修改原集合,用于从 Map 中删除指定的键值对。
key:
any
,要删除的键。返回:
isDeleted:
boolean
,返回是否删除成功,不会抛出错误。
核心特性:
键删除机制:使用 SameValueZero 算法匹配键:
NaN
被视为相同的键(即使NaN !== NaN
)-0
和+0
被视为相同键- 引用类型按内存地址区分
删除后效果:
- Map 大小变化:
map.size
立即减少 - 迭代器更新:后续遍历不再包含该键值对
- 内存释放:删除引用类型键可能触发垃圾回收
jsconst map = new Map([ ['a', 1], ['b', 2], ['c', 3] ]); console.log(map.size); // 3 map.delete('b'); console.log(map.size); // 2 // 遍历验证 for (let key of map.keys()) { console.log(key); // 输出 'a' 和 'c' }
- Map 大小变化:
示例:
基本使用:
jsconst userRoles = new Map(); // 添加用户角色 userRoles.set('alice', 'admin'); userRoles.set('bob', 'editor'); userRoles.set(NaN, 'guest'); userRoles.set(null, 'anonymous'); // 对象键示例 const charlie = { name: 'Charlie' }; userRoles.set(charlie, 'viewer'); // 删除操作 console.log(userRoles.delete('alice')); // true console.log(userRoles.delete('eve')); // false(不存在) console.log(userRoles.delete(NaN)); // true console.log(userRoles.delete(null)); // true console.log(userRoles.delete(charlie)); // true console.log(userRoles.delete({ name: 'Charlie' })); // false(不同对象)
安全删除函数:
删除键之前先判断该键是否存在
js// 安全删除函数 function safeRemove(map, key) { if (map.has(key)) { map.delete(key); return `已删除 ${key}`; } return `键 ${key} 不存在`; }
批量遍历删除:不存在也不报错
js// 批量删除 const keysToRemove = ['inactive1', 'inactive2']; keysToRemove.forEach(key => userRoles.delete(key)); // 不存在也不报错
clear()
map.clear():()
,修改原集合,用于完全清空 Map 中的所有键值对。
核心特性:
完全清空:
移除 Map 中所有键值对:
jsconst map = new Map([ ['a', 1], ['b', 2], ['c', 3] ]); map.clear(); console.log(map.size); // 0
触发垃圾回收:
删除键值对后,若键/值无其他引用,可能触发垃圾回收:
jslet obj = { data: 'test' }; const map = new Map([[obj, 'value']]); map.clear(); // 此时 { data: 'test' } 可能被垃圾回收
引用保持:Map 对象引用不变(变量仍指向同一内存地址)。
迭代器失效:清空后任何现有迭代器(如
keys()
,values()
)将立即失效。原型链不受影响:仅清除实例数据,不改变原型方法。
示例:
基本使用:
js// 创建 Map const configMap = new Map([ ['theme', 'dark'], ['fontSize', 16], [Symbol('token'), 'xyz123'] ]); console.log(configMap.size); // 3 // 清空 Map configMap.clear(); console.log(configMap.size); // 0
验证数据清除:
js// 验证数据清除 console.log(configMap.get('theme')); // undefined console.log(configMap.has('fontSize')); // false
forEach()@
map.forEach():(callbackFn, thisArg?)
,用于按插入顺序遍历 Map 的所有键值对并执行回调函数。
callbackFn:
(value?,key?,map?)=>undefined
,为每个键值对执行的函数。value?:
any
,当前键值对的值。key?:
any
,当前键值对的键。map?:
Map
,正在遍历的 Map 对象本身。
thisArg?:
any
,执行 callbackFn 时用作 this 的值。
核心特性:
遍历顺序:
严格按键值对的插入顺序执行:
jsconst map = new Map(); map.set('a', 1); map.set('b', 2); map.forEach((v, k) => console.log(k)); // 输出 'a' 然后 'b'
遍历范围
- 包含所有键值对(无论键/值类型)
- 添加新元素:遍历期间添加的新元素不会被访问
- 删除已访问元素:已访问过的元素被删除后不影响后续遍历
- 删除未访问元素:未访问元素被删除后跳过不访问
jsconst map = new Map([['a', 1], ['b', 2], ['c', 3]]); map.forEach((v, k) => { if (k === 'b') { map.delete('c'); // 删除未访问元素 'c' map.set('d', 4); // 添加新元素(不会被访问) } console.log(k, v); // 输出: // 'a' 1 // 'b' 2 (元素 'c' 被删除不会输出) });
不可中断:
没有内置中断机制(区别于
for...of
+break
):js// 无法使用 break/return 中断 map.forEach((v, k) => { if (k === 'stop') return; // ❌ 不会中断遍历 });
thisArg
参数作用jsconst counter = { count: 0, increment() { this.count++; } }; map.forEach(function() { this.increment(); // this 指向 counter }, counter);
示例:
基本使用:
js// 基本遍历 const userMap = new Map([ ['id', 101], ['name', 'Alice'], ['email', 'alice@example.com'] ]); userMap.forEach((value, key) => { console.log(`${key}: ${value}`); }); // 输出: // id: 101 // name: Alice // email: alice@example.com