请查看以下代码段:
class Node {
constructor(num) {
this.num = num;
this.right = null;
this.left = null;
}
}
let node1 = new Node(1);
let node2 = new Node(2);
let hash = {};
hash[node1] = 1;
console.log(hash[node2]); // prints "1" ????
为什么hash [node2]返回值为1?只有node1存储在哈希中...
如果你记录你的对象你得到这个:
{ '[object Object]': 1 }
因此,为什么以下记录1,因为node2被解释为[object Object]
console.log(hash[node2]); //This is evaluating hash['object Object'] (Again)
为了解决这个问题,有很多方法,一种是使用JSON API对对象进行字符串化,并使用返回值作为键。
EG
hash[JSON.stringify(node1)] = 1;
现在你拥有的是:
{'{"num":1,"right":null,"left":null}': 1 }
因此,正如预期的那样,访问hash [node2]现在将是未定义的。
hash[node2] === undefined; //true
hash[JSON.stringify(node2)] === undefined; //true
您可能想要围绕此创建一个小API。作为一个非常粗略的例子:
class Hash {
constructor () {
this.hashes = {};
}
get (key) {
return this.hashes[JSON.stringify(key)];
}
set (key, value) {
this.hashes[JSON.stringify(key)] = value;
}
}
const hashStore = new Hash();
hashStore.set({foo: 'bar'}, 1);
hashStore.set({foo: 'cheese'}, 2);
console.log(hashStore.get({foo: 'bar'})); // 1
console.log(hashStore.get({foo: 'cheese'})); //2
或者,如果您只使用对象作为“您的控件”中的键,那么正如Jakub Keller在其答案中指出的那样,您可以覆盖Node类的toString函数。
这两种方法的后退都是“唯一性”,要么两种方法都是一种稳定的方法,你要为每个对象引入一个唯一的密钥,如果你使用Jakub Keller的方法,你就会在toString中使用那个唯一的密钥覆盖。
这两种方法都满足一组需求,如果你要存储文字,一组不同的对象作为你的键,我可能会采用我的方法,并让API为存储在get中的每个对象写一个自定义的唯一ID。方法,再次不完美,因为你可以覆盖现有的密钥。
该值显示为1
,因为任一对象的哈希在技术上是[object Object]
。因此,你的关键是[object Object]
。
尝试重写Node类的toString
并通过调用toString
显式转换它:
class Node {
constructor(num) {
this.num = num;
this.right = null;
this.left = null;
}
toString() {
return this.num;
}
}
let node1 = new Node(1);
let node2 = new Node(2);
let hash = {};
hash[node1] = 1;
console.log(hash[node2.toString()]);
// output: 2
您可以在哈希对象上使用Object.assign()方法,如下所示:
hash = Object.assign({node1, node2}, {});