Introduce
One nice day, you finish coding, write cool code, take data and change them to show up, you see the error undefined. And so your app crashes. It is annoying, right?
If you’ve been following JavaScript for a while, then this error is no stranger to you. Now handle it. The genres
variable is being undefined
, which requires an if
condition to ensure this case.
1 2 3 4 5 6 7 | <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> loading <span class="token operator">&&</span> <span class="token operator">!</span> error <span class="token operator">&&</span> genres <span class="token punctuation">.</span> length <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// do something here</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// handle if something evaluates to not true in the if statement</span> <span class="token punctuation">}</span> <span class="token comment">// program continues on its merry way</span> |
So the app works normally again.
Is there a better way to keep checking the value of an object before accessing its properties? JavaScript certainly wants to help you handle this as well.
And that’s what I want to introduce in this article, the optional chaining operator ?.
.
The optional chaining operator is a proposal currently in Stage 4, which allows for short-circuiting if the reference is null
or undefined
then returns the undefined
value instead of throwing errors from which the program cannot continue. This makes the expressions shorter and simpler when accessing the properties of an object whose viability is not guaranteed.
The syntax of the optional chaining operator (?.)
It sounds a bit complicated, the syntax is not ?.
Okay then, but in this section, I want to explain more about the syntax of the operator in each case with example code will help you to better understand it.
Optional chaining with object
1 2 3 4 5 | <span class="token keyword">let</span> possibleNull <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> <span class="token keyword">let</span> value <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> <span class="token keyword">let</span> result <span class="token operator">=</span> possibleNull <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token punctuation">[</span> value <span class="token operator">++</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 0 as value was not incremented</span> |
Although the variable possibleNull
is null
, the result still doesn’t return an error because of the ?.
Operator ?.
helped you handle it. It will skip that segment and continue to execute the program, so that the value variable at this time will not increase the value, remaining at 0.
Optional chaining with object properties
Below is an example of optional chanining when accessing properties of an object
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">const</span> adventurer <span class="token operator">=</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Alice'</span> <span class="token punctuation">,</span> cat <span class="token punctuation">:</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Dinah'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> dogName <span class="token operator">=</span> adventurer <span class="token punctuation">.</span> dog <span class="token operator">?</span> <span class="token punctuation">.</span> name <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> dogName <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// expected output: undefined</span> |
If the operand on the left of ?.
is null or undefined, the calculation expression will have the value undefined
.
You can also use the optional chaining operator when accessing an attribute as an expression using square brackets as in the following case:
1 2 | <span class="token keyword">let</span> nestedProp <span class="token operator">=</span> myObj <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token punctuation">[</span> <span class="token string">'prop'</span> <span class="token operator">+</span> <span class="token string">'Name'</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> |
Optional chaining with function call
You can use it in the case of calling a function that doesn’t necessarily already exist.
1 2 | <span class="token keyword">let</span> response <span class="token operator">=</span> someInterface <span class="token punctuation">.</span> customFunction <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
By using optional chaining with the function call, the expression will immediately return undefined
instead of throwing an exception if the method is not found. It will be extremely useful when you use the API with a method that is not available, due to the version or method that is not supported on user devices …
Access the element of the array with optional chaining
Arrays with optional chaining are also quite interesting, you can access the element by passing an index, and if the index does not exist in the network, the program will not fail.
1 2 3 4 | <span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token number">3</span> <span class="token punctuation">]</span> <span class="token keyword">let</span> arrayItem <span class="token operator">=</span> arr <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token punctuation">[</span> <span class="token number">3</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> arrayItem <span class="token punctuation">)</span> <span class="token comment">// prints: undefined</span> |
Stacked optional chaining
Another cool thing is that you can use optional chaining multiple times with the same nested object
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">let</span> customer <span class="token operator">=</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">"Sean"</span> <span class="token punctuation">,</span> details <span class="token punctuation">:</span> <span class="token punctuation">{</span> age <span class="token punctuation">:</span> <span class="token number">43</span> <span class="token punctuation">,</span> location <span class="token punctuation">:</span> <span class="token string">"Trinidad"</span> <span class="token comment">// detailed address and subscription service frequency is unknown</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">let</span> customerSubscription <span class="token operator">=</span> customer <span class="token punctuation">.</span> details <span class="token operator">?</span> <span class="token punctuation">.</span> subscription <span class="token operator">?</span> <span class="token punctuation">.</span> frequency <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> customerSubscription <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// prints: undefined</span> <span class="token keyword">let</span> customerCity <span class="token operator">=</span> customer <span class="token punctuation">.</span> details <span class="token operator">?</span> <span class="token punctuation">.</span> address <span class="token operator">?</span> <span class="token punctuation">.</span> city <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> customerCity <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// prints: undefined</span> |
Both customerSubscription
and customerCity
variables end up undefined
because they are not defined in the customer
object. And you can do the same with the function. Eg:
1 2 | <span class="token keyword">let</span> duration <span class="token operator">=</span> vacations <span class="token punctuation">.</span> trip <span class="token operator">?</span> <span class="token punctuation">.</span> getTime <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Combined with the nullish coalescing operator
The nullish coalescing operator (also in the proposal of Stage 4) is written as ??
is a logical operator that returns its right operand when its left operand is null or undefined
, otherwise it returns its left operand. For example:
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> foo <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token operator">?</span> <span class="token operator">?</span> <span class="token string">'default string'</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> foo <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// expected output: "default string"</span> <span class="token keyword">const</span> baz <span class="token operator">=</span> <span class="token number">0</span> <span class="token operator">?</span> <span class="token operator">?</span> <span class="token number">42</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> baz <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// expected output: 0</span> |
Now combining 2 operators, you will get as in this example:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">let</span> customer2 <span class="token operator">=</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">"Paige"</span> <span class="token punctuation">,</span> details <span class="token punctuation">:</span> <span class="token punctuation">{</span> age <span class="token punctuation">:</span> <span class="token number">30</span> <span class="token comment">// once again a city is not provided on this object</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> customerCity2 <span class="token operator">=</span> customer2 <span class="token operator">?</span> <span class="token punctuation">.</span> city <span class="token operator">?</span> <span class="token operator">?</span> <span class="token string">"City not provided"</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> customerCity2 <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// prints: "City not provided"</span> |
When a city
attribute does not exist, first of all thanks ?.
it becomes undefined
, next, operator ??
will set it to the right operand “City not provided”.
So you can create default values when the property is forgotten, reducing the debugging time for bad data. It is great, isn’t it. ?
Conclude
The optional chaining operator helps us minimize errors when the value of an object or function does not exist. Because it was still a proposal at Stage 4 at the time of this writing, it is not fully supported by all browsers or is standardized into JavaScript. Chrome, Firefox and Opera already support it, Edge, Safari and Internet Explorer do not.
Thank you for following along, hopefully you will put it to use when this operator is officially standardized, and it will help you to simplify the code a lot more.
Source: https://itnext.io/javascripts-optional-chaining-proposal-bc9e6e5f2877