In praise of Javascript’s undefined

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:

  1. 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.
  2. external libraries are not designed to deal with the complexities of getting V they just want V.
  3. Maybe V is part of a larger calculation where some value of V must be used. The caller supplies defaultV if there is no V. But the calculation involving V should be skipped if no V is available.
  4. Callers have their own timing constraints and may not be able to wait for V to arrive.
  5. the caller is happy to use a cached value of V even if Vcached is expired.
  6. 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
  7. 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.
  8. 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.

This entry was posted in software design, technical. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *