There are multiple questions here in SO that are similar to my question, but none really answers it completely.
Basically, I want to have objects as keys in JavaScript. I know it is possible with Map
, however, it doesn't fully apply to my use-case. Here is the reason:
Let's say I have two objects, var d1 = {a: 1, b: 2}
and var d2 = {a: 1, b: 2}
, and a Map var m = new Map()
. When adding d1
to m
, when I call m.get(d2)
I will get undefined. I assume it is because Map
works in a reference-like manner.
However, I want the following functionality:
m.set(d1, 'hit');
m.get(d2) // should return 'hit' because properties and values of d1 = d2
One approach I thought of was not to use Map
, but a simple JS object. Keys would be JSON.stringify(obj)
and when I want to get a value from the object, I use JSON.parse(key)
and then perform object equality check (Object.getOwnPropertyNames
and then checking one-by-one).
However, I feel that this approach is way more complex and time-consuming than it should be. What I am looking for is probably a hash function of some sort that would efficiently map a object with keys of type String
to values of type Number
(integer in my case). Also, the ordering can be different (d1 = {a: 1, b: 2}
should equal d2 = {b: 2, a: 1}
).
How to design an efficient hash function to work with either JS Objects/Maps to perform the above-mentioned operations?
Write a function that turns the object into a string with the keys in a consistent order.
function objToKey(obj) {
Object.keys(obj).sort().map(k => `${k}:${obj[k]}`).join(',');
}
var d1 = {a: 1, b: 2},
d2 = {b: 2, a: 1},
m = new Map();
m.set(objToKey(d1), "foo");
console.log(m.get(objToKey(d2)));