我在 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
在此代码中,我想使用一对
Int
作为我的地图的键 (allElem
)。Map
比较 javascript 中的对象。Map
确实使用 SameValueZero 算法 来比较密钥。这意味着引用相等用于对象,因此如果您有 a = new PairKey(1, 2)
和 b = new PairKey(1, 2)
,它们不是同一个对象 - a !== b
。
那么你能做什么来解决这个问题呢?基本上有两种方法可以解决这个问题:
new PairKey
总是返回相同的对象此外,您还可以对
Map
进行子类化,其中所有方法都被覆盖,以便它们依靠上述技术之一专门处理 PairKey
。
不幸的是,如果没有弱引用和内存泄漏,哈希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
您的代码失败的原因是 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));
我很抱歉提出这个老问题,但我发现了一个非常有趣的解决方案,灵感来自于Bergi的答案和提到的不可能的哈希consing。
在下面的代码中,您还可以使用
Map
代替 Record
(对象)。
class PairKey {
private static cache: Record<string, PairKey> = {};
constructor(private _x: number, private _y: number) {
const key = PairKey.key(_x, _y);
if (PairKey.cache[key]) {
return PairKey.cache[key];
}
PairKey.cache[key] = this;
}
private static key(x: number, y: number) {
return `${x}_${y}`;
}
get x() {
return this._x;
}
set x(x_pos: number) {
this._x = x_pos;
}
get y() {
return this._y;
}
set y(y_pos: number) {
this._y = y_pos;
}
}
const allElem = new Map<PairKey, string>();
allElem.set(new PairKey(1, 2), 'a');
allElem.set(new PairKey(2, 3), 'b');
console.log(allElem.has(new PairKey(1, 2))); // Returns true
您的地图键是一个对象。
console.log
返回 false
,因为您正在创建一个 新对象 来检索它们的密钥。拥有同一对并不重要。重要的是它是一个不同的新对象。
如果您想检索与
new pairKey(1,2)
对应的值,您必须执行以下操作:
let key = new pairKey(1,2);
allElem.set(key, 'a');
console.log(allElem.has(key));
换句话说,如果您使用对象作为键,请确保使用相同的对象来检索值。