Is the use of Objects as keys inefficient in Javascript?
Let's say I define a couple of classes. Then I create object of each class. I want to save the objects in a map keyed by their classes, so that I can retrieve the object based on its class.
(I'm using ES6 syntax, however the question may remain the same for legacy Javascript with class replaced by function)
// Alternative 1
class Apple {
}
class Banana {
}
let fruitInBag = {};
fruitInBag[Apple] = new Apple();
fruitInBag[Banana] = new Banana();
Alternatively I could also write following with the same outcome
// Alternative 2
class Apple {
}
class Banana {
}
const FRUIT_TYPE_APPLE = 1;
const FRUIT_TYPE_BANANA = 2;
let fruitInBag = {};
fruitInBag[FRUIT_TYPE_APPLE] = new Apple();
fruitInBag[FRUIT_TYPE_BANANA] = new Banana();
The second alternative is awkward, because I've to define and maintain the constants separate from class definitions. Therefore I would prefer the first one. But is the first approach inefficient? Is the Object
smart enough to implement the first alternative efficiently?
The Keys in a Javascript object are always strings. No Integers and no functions (Classes). Use a ES6 Map for this!
I updated the code snippet in the question to correctly reflect the problem. After having done that and taking the suggestions from the comments and deleted answer, I did some analysis in Chrome devtools as follows.
As you can see from the picture, I defined a class in both ES6 ( class Apple
) and ES5 ( function FnApple
) manner. Then I kept them in regular ES5 object ( mapA
) and later ES6 map ( mapB
). In all the cases the browser stringifies the class definition completely and uses that string as a key. This works, because complete stringification of class makes it distinct. (I was afraid the stringification will the a dump [Object]
string).
However this also means that using the class or function object as key will make the map key of indeterminately long size. In real world scenario when classes have long definitions, the key can go upto few KBs. Given this, it makes sense that one should use independently defined integers for keys in maps.
Update
In case of ES6 map, my test above is incorrect. I assigned the key-value to the mapB object using []
syntax, which makes it store the key-value as member of object like ES5 (because even ES6 Map instance is an object). The right way to set key-value on ES6 map is to use get(),set() API. After doing that I see that the type of keys is indeed function
and not String
for ES6 Map.