【问题标题】:How to get deep-equality of keys in ES6 Map? Alternative to using complex object as ES6 Map key?如何在 ES6 Map 中获得深度相等的键?替代使用复杂对象作为 ES6 Map 键?
【发布时间】:2019-07-29 22:58:43
【问题描述】:

这里有一些示例 Javascript (ES6) 代码,它并没有按照人们的直觉想象。

const exampleMap = new Map([[{a: 1}, 2]]);
console.log(exampleMap.get({a: 1}));

事实证明,这会打印出undefined。为什么?推理在this StackOverflow answer 中介绍。根据the MDN entry for MapMap 使用=== 来表示密钥相等。并且,根据the MDN entry for ===Objects 通过引用相等性进行比较。

这一切都很好。它完全按照文档所说的去做。不幸的是,上面的代码试图做的事情会非常有用,即使它不是规范中的实际行为。

如何使用Map,或者我应该使用什么来代替Map,来获取键值查找,其中键是通过对象深度相等语义进行比较的?

【问题讨论】:

标签: javascript ecmascript-6


【解决方案1】:

您可以创建自己的函数,在其中传递要获取其值的地图 (m),以及要在地图中搜索的 key。然后你可以对你的键进行字符串化,这样你就可以在你的地图中搜索键并将它们与这个字符串化的键进行比较

const exampleMap = new Map([[{a: 1}, 2]]);

const getMapVal = (m, key) => {
  const strKey = JSON.stringify(key);
  return m.get(Array.from(m.keys()).find((k) => JSON.stringify(k) === strKey));
}

console.log(getMapVal(exampleMap, {a: 1})); // 2 (gives undefined if key doesn't exists)

【讨论】:

    【解决方案2】:

    这里有一个做深度相等检查的东西。它依赖于JSON.stringify,因此对于非常大的对象键可能是一个性能问题。这也更新了Map 原型,以便以与.get 相同的方式使用。

    Object.defineProperty(Map.prototype, 'deepCheck', {
      value: function(lookupKey) {
        let lookupValue;
        const lookupKeyStr = JSON.stringify(lookupKey);
        if (this == null) {
          throw new TypeError('this is null or not defined');
        }
    
        const iterator = this.entries();
        let result = null;
    
    
        while (true) {
          result = iterator.next();
          if (result.done) {
            break;
          }
          if (JSON.stringify(result.value[0]) === lookupKeyStr) {
            lookupValue = result.value[1];
          }
        }
    
        return lookupValue;
      }
    });
    
    const exampleMap = new Map([[{a: 1}, 2]]);
    
    console.log(exampleMap.deepCheck({a: 1}));

    【讨论】:

      【解决方案3】:

      您需要以某种方式比较或获取对用作 Map 键的确切对象的引用。一种选择是遍历 Map 的 entries,并检查其键的 a 值为 1:

      const exampleMap = new Map([[{a: 1}, 2]]);
      const foundEntry = [...exampleMap.entries()]
        .find(([key, val]) => key.a === 1);
        
      console.log(
        foundEntry
        ? foundEntry[1]
        : 'Not found!'
      );

      另一种方法:

      const exampleMap = new Map([[{a: 1}, 2]]);
      const foundKey = [...exampleMap.keys()]
        .find(key => key.a === 1);
        
      console.log(
        foundKey
        ? exampleMap.get(foundKey)
        : 'Not found!'
      );

      【讨论】:

        猜你喜欢
        • 2015-12-16
        • 2017-12-15
        • 1970-01-01
        • 1970-01-01
        • 2016-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多