Optional Chaining Operator in JavaScript

Adam Bene
2 min readAug 9, 2017

--

Optional Chaining Operator in JavaScript

The Problem of Property Chaining

All of us usually confronts the situation where an expected member of a property chain is undefined or null.

var user = { name: 'Joe' }
var zip = user.address.zip // ⚡⚡⚡
Uncaught TypeError: Cannot read property 'zip' of undefined

In this example we expect user.address.zip to exist but for some reason the address is missing from the user object.

Workaround #1: Logic Expressions

var user = { name: 'Joe' }
var zip = user
&& user.address
&& user.address.zip

Noisy and verbose.

Workaround #2: Ternary Operators

var user = { name: 'Joe' }
var zip =
user === undefined
? undefined
: user.address === undefined
? undefined
: user.address.zip

Even more noisy and verbose.

Workaround #3: Try-Catch

var user = { name: 'Joe' }
var zip
try {
zip = user.address.zip
} catch (error) {
zip = null
}

Breaks control and has own scopes.
Also a bit noisy.

Of course there are many workarounds, property selector libraries etc.

Optional Chaining Operator

There is a new proposal for ECMAScript. It is currently in stage 1 and there are 4 stages.

var user = { name: 'Joe' }
var zip = user?.address?.zip

Voilà, zip is undefined and does not throw an error.

The syntax supports function and constructor calls as well:

var address = getAddressByZip.?(12345)

If getAddressByZip is a function it is called, otherwise, the expression is evaluated as undefined.

Set Up Babel — Working Example

We need alpha 7 version from Babel.

npm install --save-dev babel-cli@7.0.0-alpha.19
npm install --save-dev babel-plugin-transform-optional-chaining@^7.0.0-alpha.13.1

Create a .babelrc file in the project root:

{
"plugins": ["transform-optional-chaining"]
}

Create an index.js to test the optional chaining operator.

var user = { name: 'Joe' }
var zip = user?.address?.zip
console.log(zip)

Then run it:

node_modules/.bin/babel-node index.js

Or transpile the code:

node_modules/.bin/babel index.js

The Transpiled Code

Transpiled version of the index.js above:

var _user$address;var user = {
name: 'Joe'
};
var zip =
user == null
? void 0
: (_user$address = user.address) == null
? void 0
: _user$address.zip;
console.log(zip);

The transpiled code is constructed of nested ternary operators similar to the code in workaround #3 above. The main difference is that this code is optimized for edge cases also.

See Also

--

--