One of the unique[*] features of javascript is two different ways to represent ‘no value’: null
and undefined
.
[*] = unique as many popular languages do not have both null
and undefined
.
In my years and years of programming Java, I always missed not having a way to represent the ‘not value YET’ condition.
null
always end up being needed to represent the ‘no value’ condition which made it difficult to handle the ‘no value YET’ condition.
‘no value’ is a definitive terminal condition: there is no value available. Period.
‘no value YET’ means the information is still being retrieved/calculate, a non-terminal condition. The requestor should ask again at some future date.
The ‘no value YET’ condition occurs frequently in internet coding. For example, server A initiates a request to another server, server B, for some information (V
). V
could take seconds to arrive or may never arrive.
The code on server A wishes to continue to run while waiting for server B to respond with the value of V
. What value for V
should be used for the server A code that is asking for V
‘s value? In an idealized world all the calling code uses concepts like Promises and Futures and the problem is kicked upstairs.
In the real world, often times this doesn’t work in practice:
- This change almost certainly requires changing the contract about the object/value being returned. Every caller would then need to be changed. Often times this change will cause ripple effects that extend through massive amounts of the code.
- external libraries are not designed to deal with the complexities of getting
V
they just wantV
. - Maybe
V
is part of a larger calculation where some value ofV
must be used. The caller suppliesdefaultV
if there is noV
. But the calculation involvingV
should be skipped if noV
is available. - Callers have their own timing constraints and may not be able to wait for
V
to arrive. - the caller is happy to use a cached value of
V
even ifVcached
is expired. - exposing the details of the
V
being ‘on its way’ is too much information for the caller. The caller doesn’t have any alternative path available - returning a value that is some type other than the return type expected by the caller is breaking the function’s contract with all the existing calling code.
- Lastly, leaking the implementation details of getting
V
means that if those details change all the callers are impacted.
This is where the beauty of null and undefined come into play.
For those callers that just need V
today, null and undefined can be easily tried identically:
var V = undefined; console.log( V == null ); console.log( null == null );
both return true.
so ….
if ( V == null ) V = defaultV;
Which is the same code the callers previously had. Thus, the vast majority of the existing callers continue unchanged.
For the minority of callers wanting to know if they should come back for the final answer:
V === undefined
will give them the answer they need.
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.