Trimming JavaScript: ditch verbosity, gain readability

danbars

Dan Bar-Shalom

Posted on April 21, 2024

Trimming JavaScript: ditch verbosity, gain readability

Are you familiar with expressions like these:

  • a !== undefined && a !== null ? a : b
  • if (a.x === undefined || a.x === null) { a.x = b }
  • { foo: foo, bar: bar }
  • a ? a.b : undefined
  • function 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
Enter fullscreen mode Exit fullscreen mode

To this:

a ?? b
Enter fullscreen mode Exit fullscreen mode

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 
}
Enter fullscreen mode Exit fullscreen mode

to this:

a.x ??= b
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

to that:

const name = 'john doe'
const age = 32
const talk = text => void console.log(text)
const person = {
  name,
  age,
  talk
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

with that:

a?.b
Enter fullscreen mode Exit fullscreen mode

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, if customMethod exists, but it is not a function, you'd still get an exception someInterface.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 get undefined instead 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 implicit return.
  • 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 
}
Enter fullscreen mode Exit fullscreen mode

with this

const getX = o => o.x
Enter fullscreen mode Exit fullscreen mode

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 super or be used as constructors
💖 💪 🙅 🚩
danbars
Dan Bar-Shalom

Posted on April 21, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related