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
相关产品推荐
相关产品推荐

