Are you familiar with expressions like these:
a !== undefined && a !== null ? a : bif (a.x === undefined || a.x === null) { a.x = b }{ foo: foo, bar: bar }a ? a.b : undefinedfunction getX(o) { return o.x }
What do they all have in common? They are highly verbose, and all have a nice shorthand alternatives. Let's see how we can improve each one of these:
Nullish coalescing operator ??
This operator checks the value of the left hand-side operand - if it's null or undefined, it returns the right hand-side operand. Otherwise it returns the left hand-side, without evaluating the right hand-side.
This allows simplifying the following expression:
a !== undefined && a !== null ? a : b To this:
a ?? b Unlike || operator that checks for any falsy value, this operator only checks for nullish values - meaning null or undefined. Therefore it is safer to use in cases that a is a boolean which can be false or a number which can be 0, and then a || b will return the value of b
Nullish coalescing assignment ??=
This operator only evaluates the right operand and assigns to the left if the left operand is null or undefined.
So we can simplify this expression:
if (a.x === undefined || a.x === null) { a.x = b } to this:
a.x ??= b JSON shorthand syntax
The shorthand syntax was introduced with ES6 and is already pretty common.
Use it to shorten this:
const name = 'john doe' const age = 32 const talk = text => void console.log(text) const person = { name: name, age: age, talk: talk } to that:
const name = 'john doe' const age = 32 const talk = text => void console.log(text) const person = { name, age, talk } Optional chaining ?.
This operator accesses an object's property just like . does. However, unlike ., if the object is null or undefined, the expression will return undefined instead of throwing an error.
This allows replacing this code:
a ? a.b : undefined with that:
a?.b This operator is pretty strong, and can be used in various ways:
- Chaining:
a?.b?.c?.d - Call interface method:
someInterface.customMethod?.()Note that in this case, ifcustomMethodexists, but it is not a function, you'd still get an exceptionsomeInterface.customMethod is not a function - Access dynamic property with bracket notation:
x?.[propname] - Access array items:
array?.[50]- even if array is nullish, you'd getundefinedinstead of an exception
Arrow functions
There's a lot to say about arrow functions, but in the context of this post I want to focus on a specific use - 1 liner methods that calculate something or access some property. They have 2 attributes that help with code shortening:
- Arrow functions that do not have a block body wrapped with curly brackets
{/*...*/}have an implicitreturn. - in a single-param arrow function you do not have to put the argument in parentheses Meaning, you can change this:
function getX(o) { return o.x } with this
const getX = o => o.x This is super useful, for example, for mapping functions.
Note that there are some caveats though:
- Arrow functions do not have
this - Arrow functions do not have
arguments. You can use spread operator instead. E.g(...args) => args[0] - Arrow functions cannot call
superor be used as constructors
Top comments (0)