Reputation: 15048
Please look at the following code snippet:
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" ????
Why does hash[node2] returns a value of 1? Only node1 was stored in the hash...
Upvotes: 1
Views: 598
Reputation: 1
You can use Object.assign() method on your hash object like this:
hash = Object.assign({node1, node2}, {});
Upvotes: 0
Reputation: 6502
If you log your object you get this:
{ '[object Object]': 1 }
Hence why the below logs 1, as node2 is being interpreted as [object Object]
console.log(hash[node2]); //This is evaluating hash['object Object'] (Again)
To get around this, there are a number of approaches, one would be to stringify your object using the JSON API, and use the return value as the key.
E.g.
hash[JSON.stringify(node1)] = 1;
Now what you have is:
{'{"num":1,"right":null,"left":null}': 1 }
And thus, accessing hash[node2] will now be undefined, as expected.
hash[node2] === undefined; //true
hash[JSON.stringify(node2)] === undefined; //true
You would probably want to create a little API around this. As a very rough example:
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
Alternatively, if you are only using objects as keys which are in 'your control', then as Jakub Keller points out in his answer, you could override the toString function of your Node class.
The fallback of both approaches here is 'uniqueness', for either method to be a stable approach, you would want to introduce a unique key for each object, if you go with Jakub Keller's approach, you'd use that unique key in the toString override.
Both approaches satisfy a set of needs, if you're storing literals, an array of different objects as your keys, i'd probably go with my approach, and have the API write a custom, unique ID onto each object stored in the get method, again not perfect, as you could overwrite an existing key.
Upvotes: 3
Reputation: 497
The value shows as 1
because the hash of either object is technically [object Object]
. Therefore, your key is [object Object]
.
Try overriding the Node class's toString
and explicitly converting it by calling 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
Upvotes: 2