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

JavaScript中扩展Map类的keys()等生成器方法优化咨询

问题描述

我需要让对象作为Map的键使用,并且要求值相同的对象(即使引用不同)能被识别为同一个键。但原生Map是按引用匹配键的,示例如下:

let newMap = new Map()
const obj1 = {'a': 1, 'b' :2}
newMap.set(obj1, 123)
const copyObj1 = {...obj1}
console.log(newMap.get(obj1)) // 返回123
console.log(newMap.get(copyObj1)) // 返回undefined

我需要第二个console.log也返回123,因此扩展了Map类,通过JSON.stringify处理传入的对象:

class CoordMapper extends Map {
    set = (k: ISquareCoordinate, v: Array<ISquareCoordinate>) => {
        const stringifiedKey = JSON.stringify(k)
        return super.set(stringifiedKey,v)
    }

    get = (k: ISquareCoordinate) => {
        const stringifiedKey = JSON.stringify(k)
        return super.get(stringifiedKey)
    }
}

但重写keys()方法时,当前实现会一次性加载所有键到数组中,我希望避免这种情况:

* keys() {
   const keysArr = [...super.keys()]
   for (const key of keysArr){
      yield JSON.parse(key)
   }
}

有没有更优的实现方式?

优化方案

不需要提前把所有键转成数组,直接遍历原生keys()的生成器即可实现懒加载,不会一次性加载所有键:

* keys() {
  for (const stringKey of super.keys()) {
    yield JSON.parse(stringKey);
  }
}

同理,entries()也可以用相同思路优化,确保遍历过程中按需解析键:

* entries() {
  for (const [stringKey, value] of super.entries()) {
    yield [JSON.parse(stringKey), value];
  }
}

而values()方法无需修改,原生实现已经直接返回对应的值,不需要处理键的转换。

额外注意事项

  • JSON.stringify对对象属性顺序敏感:如果两个对象值相同但属性顺序不同,会被视为不同的键。若要避免这种情况,可以在序列化前先给属性排序:
const stringifyKey = (obj: ISquareCoordinate) => {
  return JSON.stringify(Object.fromEntries(Object.entries(obj).sort()));
}
  • 特殊属性处理:如果对象包含undefined、function或Symbol类型的属性,JSON.stringify会直接忽略这些属性,可能导致不符合预期的键匹配,需要根据业务场景提前处理这类情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:15:11