5 neat javascript tricks to make your life easier

Table of contents

Nullish operators

To understand nullish operators, we need to define what "nullish" means first: A variable's value is considered nullish if it is null or undefined. Code will occasionally have to check if a value is nullish, to set default values for code further down that expects genuine values like objects or strings.

As a quick way to return either a value or a fallback if it is nullish, use the nullish coalescing operator ?? :

return x ?? "default"

Returns the value of x if it isn't nullish, else it returns the string "default" instead.

If you want to assign a default value to a variable, but only if it is currently nullish, you can use the nullish coalescing assignment ??= :

let x ??= 5

This will set the variable x to 5 if it is currently null or undefined.

Optional chaining

Chaining property and function accesses together is a common way to shorten javascript code. But what if you suspect one or more elements to null / undefined? When trying to access child properties or functions of nullish elements, a TypeError exception will be thrown. If you want to simply access a child element or do nothing if it is nullish, you can use the optional chaining operator ?. :

let car = {}
let carModel = car.model?.name

In this example, the car variable has no property model, so car.model is undefined. Trying to access undefined.name will throw a TypeError exception. The optional chaining operator circumvents this by short-circuiting the code the moment a nullish child property is accessed and returns undefined instead

One important thing to note is that the operator is placed after the property you suspect of being nullish. This leads to a not immediately obvious syntax for functions:

let car = {}
let carModel = car.drive?.()

Here the optional chaining operator is placed between the name of the nonexistent function and the parenthesis () used to execute it. This is because accessing car.drive itself is legal and returns undefined, but trying to execute undefined() will throw the exception, thus the operator is placed between them.

Ternary operator

The ternary operator is often used as a single-line shorthand for an if/else condition. It is used by providing a condition, followed by a ?, the code to run if the condition is true, then a : and the code to run if the condition is false:

2 > 1 ? console.log("True") : console.log("False")

Here, 2 > 1 is the condition. The condition returns true, so the first console.log() call is executed. If it were false, the second one would be called instead.

Spread Syntax

The spread syntax ... has different behaviours depending on context. In a function's parameter list, it will catch all parameters and return them as an array:

function greet(...guests){
    console.log("Hello ", guests)
}

This allows for the definition of variadic functions that take any number of parameters, or alternatively define some and catch the rest in a single variable.

The second use is to expand an iterable's values into single values, for example:

function sum(a, b){
	return a + b
}
console.log(sum(...[4, 5]))

This passes the values of the array [4, 5] as individual parameters to the sum function.

Lastly, the spread syntax can be used to clone an object's properties into a new one:

let x = {"one": 1, "two": 2}
let y = {...x, "three": 3}
let z = {...x, ...y}

The value of y is now {"one": 1, "two": 2, "three": 3}, because the first two properties were copied from x. The contents of z are equal to y, because it contains the merged contents of x and y (and y already contained everything in x).

Destructuring

Destructuring assignments allow the extraction of object properties/array items into variables. While destructuring or arrays uses square brackets [], destructuring object properties requires curly brackets {}:

let [a, b] = [1, 2]
let {a, b} = {"a": 1, "b": 2}
let {b, a} = {"a": 1, "b": 2}

While the array simply assigns values based on sequence (first variable gets the first value of the array etc), objects use property names instead, so the order of the variables doesn't matter. This makes the last 2 lines equal. The let declaration applies to both a and b. If you change it to for example const, it will declare all destructured variables as const. If you need some to be read-only and others to be reassignable, you'll have to destructure twice.

For arrays, you can also skip values during assignment:

let [a, , b] = [1, 2, 3]

This skips the second value, setting a to 1 and b to 3 respectively.

For objects, you can use nested destructuring:

let {a, b:{c}} = { a: 1, b: { c: 2 } };

This uses nested destructuring to assign the value of b.c to the destructured variable b.

Lastly, destructuring supports the spreading syntax:

let {a, ...b} = [1, 2, 3]

Using the spread syntax allows us to catch all remaining values in a single variable. In this case, a is set to 1 and b contains the array [2, 3].

More articles

Embracing python context managers

Simplifying your code by automating resource handling

Getting help from linux man pages

Learning to navigate the linux manual pages to be productive without searching the internet

Javascript arrow functions explained

Making modern javascript code more compact

Why boring software is a smart choice

Not everything is about excitement

Common pitfalls running docker in production

Avoiding the mistakes many make when embracing containerized deployments

Modern linux networking basics

Getting started with systemd-networkd, NetworkManager and the iproute2 suite