alpav alpav - 1 month ago 9
Javascript Question

Double seek vs undefined in JavaScript Map: TryGet wanted

JavaScript map has 2 methods get and has.
Method get returns undefined if element does not exist or if value undefined was added to the map.

So if I implement my method GetAlways or such, which will return existing or add new and return if not exists, then I am stuck with the choice of sacrificing runtime performance making double map seek or sacrificing API purity equating undefined to non-existence in map and thus effectively disallowing safe addition of undefined values to the map.

Is there a third efficient and pure choice, similar to TryGet from C# ?

Code for impure choice:

Map.prototype.GetAlways = function(name){
let child = this.get(name);
if (child === undefined){ // equating undefined value to non-existence
child = {};
this.set(name, child);
}
return child;
}


Code for slow choice:

Map.prototype.GetAlways = function(name){
if(this.has(name)) // first map seek
return this.get(name); // second map seek
let child = {};
this.set(name, child);
return child;
}

Answer

undefined is meant to represent the lack of a parameter. The only occasions where it is justified to use it is to check if an argument is missing or if a function returned nothing. If someone passes undefined to your map, it's not your problem what happens.

If it bothers you, try to make JS with the C++ mindset: write explicitly in your documentation what is expected and what you guarantee. Then you don't have to waste time (and code performance) testing for those wrong parameters. That's what we call the separation of concerns.

...so my answer is, don't try to allow storing undefined in a map, yet don't do anything to prevent it in code. Just ignore the edge case and say that people aren't allowed to do that.