在JavaScript编程里,Map对象是一种存储键值对的数据结构。set() 方法专门用于向Map对象中添加新元素,或者更新已有键对应的值。如果你之前用过普通对象,可能会发现对象键只能是字符串或Symbol,而Map的键可以是任意类型,这是它很实用的一个特点。
语法与参数
mapObj.set(key, value)
-
key:要添加或更新的键,可以是任意数据类型(对象、函数、数字等)
-
value:与键关联的值
-
返回值:返回当前的Map对象,所以支持链式调用
核心特性说明
这里想多说一句,set() 方法之所以常用,是因为它处理键的唯一性非常清晰。如果使用同一个键多次调用set(),后面的值会直接覆盖前面的,不会出现重复键。这跟普通对象的行为类似,但Map对键的匹配用的是“SameValueZero”算法,NaN也可以作为键,并且多个NaN会被视为同一个键,这一点和对象不同。
还有一点值得注意,set()返回的是Map对象本身,这意味着你可以连续调用:
let map = new Map();
map.set('a', 1).set('b', 2).set('c', 3);
这种写法在某些场景下能让代码更紧凑,比如初始化一组配置数据的时候。
示例1:添加键值对
下面的例子展示了如何向Map中添加几组数据,并通过get()方法获取值:
<script>
let codeMap = new Map();
codeMap.set('框架', 'Vue.js');
codeMap.set('库', 'React');
codeMap.set('工具', 'Webpack');
console.log(codeMap.get('框架')); // Vue.js
console.log(codeMap.get('库')); // React
console.log(codeMap.get('工具')); // Webpack
</script>
输出:
Vue.js
React
Webpack
示例2:同一键多次set()的情况
在开发中,你可能需要动态更新某个键对应的数据。比如用户多次提交同一个配置项,后提交的应该覆盖之前的。这个例子就演示了覆盖的效果:
<script>
let settingMap = new Map();
settingMap.set('theme', 'dark');
settingMap.set('theme', 'light'); // 覆盖前面的值
settingMap.set('language', 'zh-CN');
console.log(settingMap.get('theme')); // light
console.log(settingMap.get('language')); // zh-CN
console.log(settingMap.get('notExist')); // undefined
</script>
输出:
light
zh-CN
undefined
这里有个小细节:当你试图获取一个不存在的键时,返回的是undefined,而不是报错。这种容错性在处理动态数据时比较友好。
个人经验分享:什么时候优先用Map而不是普通对象?
之前做项目时遇到过需要频繁增删键值对、并且键是动态生成(比如对象、数字)的场景。如果用普通对象,键会被自动转为字符串,导致一些预期外的行为。比如用数字1和字符串'1'作为键,在对象里会被视为同一个属性,但在Map中它们是不同的。这种情况下,Map的行为更符合直觉。
如果你需要遍历数据并且关心插入顺序,Map会按插入顺序迭代,而普通对象的属性顺序比较复杂(受原型链和键类型影响)。所以我一般这样判断:
-
键是字符串或Symbol,且结构相对固定→用对象
-
键类型多样,或者需要频繁增删、按插入顺序遍历→用Map
set()方法配合Map的这种特性,在管理动态数据、缓存、状态存储等场景下非常顺手。
本节课程知识要点
-
set()方法用于添加或更新Map中的键值对,返回Map对象本身,支持链式调用
-
Map的键可以是任意类型(对象、函数、数字等),且按插入顺序迭代
-
同一键多次set(),后面的值会覆盖前面的
-
获取不存在的键时返回undefined,不会报错
-
与普通对象相比,Map在处理非字符串键、动态增删、顺序迭代时更可靠
专业术语参考
-
键值对(Key-ValuePair)
-
链式调用(Chaining)
-
SameValueZero算法:JavaScript内部用于判断键是否相等的比较规则
-
迭代顺序(IterationOrder)
-
哈希表(HashTable):Map底层实现的基础数据结构