Javascript如何比较Map的键

use*_*708 5 javascript dictionary ecmascript-6

我在node.js应用程序中使用Javascript ES6功能:

class pairKey {
constructor(x_pos, y_pos) {
    this._X = x_pos;
    this._Y = y_pos;
}

get x() {
    return this._X;
}
set x(x_pos) {
    this._X = x_pos;
}

get y() {
    return this._Y;
}
set y(y_pos) {
    this._Y = y_pos;
}


var allElem = new Map();
allElem.set(new pairKey(1,2), 'a');
allElem.set(new pairKey(2,3), 'b');

console.log(allElem.has(new pairKey(1,2))); //Should return true instead return false
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我想使用一对Int地图键(allElem)作为键。
问题是我不知道如何Map比较javascript中的对象。
有人可以帮我吗?

Ber*_*rgi 7

Map确实使用SameValueZero算法来比较键。这意味着引用相等性用于对象,所以如果你有a = new PairKey(1, 2)并且b = new PairKey(1, 2)它们不是同一个对象 - a !== b

那么你能做些什么来解决这个问题呢?基本上有两种方法可以解决这个问题:

  • 不使用对象本身作为键,而是使用它的原始(例如字符串)表示,它可以从具有相同值的不同实例创建
  • 对您的关键对象使用哈希 consing,以便new PairKey在使用相同参数调用时始终返回相同的对象

此外,您还可以根据上述技术之一对Map覆盖所有方法的位置进行子类化,以便它们PairKey专门处理s。

不幸的是,如果没有弱引用和内存泄漏,哈希 consing 是不可能实现的,所以我们必须求助于第一种技术:

class Pair {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toKey() {
        return `Pair(${this.x}, ${this.y})`;
    }
    static key(x, y) {
        return new Pair(x, y).toKey();
    }
}

var allElem = new Map(); // string -> string
allElem.set(Pair.key(1, 2), 'a');
allElem.set(Pair.key(2, 3), 'b');

console.log(allElem.has(Pair.key(1, 2))); // true
Run Code Online (Sandbox Code Playgroud)


Ami*_*mit 6

您的代码失败的原因是 Map 使用相同值算法来匹配键。一个对象实例与另一个对象实例的值不同,即使两者共享相同的内在值(例如,尝试({a:1} === {a:1})-> 它为 false)。一种适合您的方法是向对象添加一个键属性,以便相同的内在值生成完全相同的键(1 比 1)。然后在设置地图条目时使用该键。请参阅示例(用于Symbol.for生成可重现的密钥):

'use strict'
class pairKey {
  constructor(x_pos, y_pos) {
    this._X = x_pos;
    this._Y = y_pos;
  }

  get x() {
    return this._X;
  }
  set x(x_pos) {
    this._X = x_pos;
  }

  get y() {
    return this._Y;
  }
  set y(y_pos) {
    this._Y = y_pos;
  }

  get key() {
    return Symbol.for(`pairKey[${this.x}:${this.y}]`);
  }
}
var allElem = new Map();
allElem.set(new pairKey(1, 2).key, 'a');
allElem.set(new pairKey(2, 3).key, 'b');

console.log(allElem.has(new pairKey(1, 2).key));
Run Code Online (Sandbox Code Playgroud)