[*] = unique as many popular languages do not have both
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 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
Vthey just want
Vis part of a larger calculation where some value of
Vmust be used. The caller supplies
defaultVif there is no
V. But the calculation involving
Vshould be skipped if no
- Callers have their own timing constraints and may not be able to wait for
- the caller is happy to use a cached value of
- exposing the details of the
Vbeing ‘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
Vmeans 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.
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.