Optional Chaining in JavaScript

idmean picture idmean · Oct 3, 2014 · Viewed 8.5k times · Source

I've been programming a lot in Swift recently. Today I did some work in JavaScipt when question popped up to me:

Is there something similar to optional chaining in JavaScript? A way to prevent undefined is not an object without any variables?

Example:

function test(){
   if(new Date() % 2){
      return {value: function(){/*code*/}};
   }
} 

test().value();

will fail half of time because sometimes test returns undefined.

The only solution I can think of is a function:

function oc(object, key){
   if(object){
      return object[key]();
   }
}

oc(test(), 'value');

I would like to be able to do something like:

test()?.value()

The part after the question mark is only executed if test returned an object.

But this is not very elegeant. Is there something better? A magic combination of operators?

Edit I know I could rewrite test to return something. But I'm wondering if there's something like optional chaining. I'm not interested in a particular solution to the above example. Something that I also can use if have no control over the function returning undefined.

Answer

Jonathan Wood picture Jonathan Wood · Mar 12, 2018

This is currently a Stage 4 proposal you can check on the progress of it here:
https://github.com/tc39/proposal-optional-chaining

You can use the babel plugin today:
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

Update 11th January 2020: Babel now supports optional chaining by default https://babeljs.io/blog/2020/01/11/7.8.0

The Optional Chaining operator is spelled ?.. It may appear in three positions:

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call

Notes:

In order to allow foo?.3:0 to be parsed as foo ? .3 : 0 (as required for backward compatibility), a simple lookahead is added at the level of the lexical grammar, so that the sequence of characters ?. is not interpreted as a single token in that situation (the ?. token must not be immediately followed by a decimal digit).

Also worth checking out:

https://github.com/tc39/proposal-nullish-coalescing

https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-nullish-coalescing-operator