You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript Map使用对象作为键时重复条目问题咨询

为什么两次插入“相同”对象后Map的size变成2?

JavaScript里的对象是引用类型,你每次写{someProperty: 0}都会创建一个全新的对象,它们在内存中的引用地址完全不同。而Map判断键是否相等用的是SameValueZero规则——对于引用类型,只有当两个值是同一个内存引用时,才会被视为同一个键。所以你两次调用map.set时用的是两个独立的对象,Map会把它们当成两个不同的键,size自然变成2。

让内容相同的对象作为同一个键的方案

根据不同场景,有几种实用的解决办法:

1. 复用同一个对象引用

如果对象可以提前定义或者重复使用,直接把它存到变量里,每次set都用这个变量:

const map = new Map();
const keyObj = {someProperty: 0};

map.set(keyObj, 0);
console.log(map.size); // 1

map.set(keyObj, 0);
console.log(map.size); // 1(此时是同一个引用,会覆盖原有值)

2. 将对象序列化为字符串作为键

如果对象的内容是可序列化的(没有函数、undefined、Symbol这类JSON无法处理的属性),可以用JSON.stringify()把对象转成字符串,用这个字符串当Map的键:

const map = new Map();

const getMapKey = (obj) => JSON.stringify(obj);
map.set(getMapKey({someProperty: 0}), 0);
console.log(map.size); // 1

map.set(getMapKey({someProperty: 0}), 0);
console.log(map.size); // 1

注意:这个方法有局限性——如果对象的属性顺序不同(比如{a:1, b:2}和{b:2, a:1}),序列化后的字符串会不一样,会被当成不同的键;另外对象里的JSON不支持类型会丢失信息。

3. 自定义基于内容比较的Map(进阶)

如果需要更灵活的内容比较逻辑,可以自己封装一个类,用深度相等判断来处理键,比如借助lodash的isEqual方法:

import _ from 'lodash';

class ContentMap {
  constructor() {
    this.innerMap = new Map();
    this.keyList = [];
  }

  set(key, value) {
    const matchIndex = this.keyList.findIndex(k => _.isEqual(k, key));
    if (matchIndex !== -1) {
      // 找到内容相同的键,替换引用并更新值
      this.innerMap.delete(this.keyList[matchIndex]);
      this.keyList[matchIndex] = key;
    } else {
      this.keyList.push(key);
    }
    this.innerMap.set(key, value);
  }

  get(key) {
    const targetKey = this.keyList.find(k => _.isEqual(k, key));
    return targetKey ? this.innerMap.get(targetKey) : undefined;
  }

  get size() {
    return this.innerMap.size;
  }
}

// 使用示例
const map = new ContentMap();
map.set({someProperty: 0}, 0);
console.log(map.size); // 1

map.set({someProperty: 0}, 0);
console.log(map.size); // 1

这个方法能处理复杂对象的内容比较,但性能比原生Map低,适合对键的内容一致性要求高的场景。

内容的提问来源于stack exchange,提问作者serlingpa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:15:50