dev env

JavaScript Tips and Tricks

By
Gideon Kreitzer
Published
2021/12/31

We'll cover what might fall into the realm of more obscure or lesser known JavaScript idioms and techniques. This will be an evolving article as I discover tidbits worth mentioning here.

Index

Writing efficient loops

Traditional loops are frequently written in a way that requires unnecessary re-evaluation of the iterable data structure's length.

function sum(...numbers) {

    let total = 0

    for (let i = 0; i < numbers.length; i++) {
        total += numbers[i]
    }

    return total
}

sum(1, 3, 5) // 9

In the sum() function above, we're using the numbers array's length property as the loop's predicate. Since numbers length won't change during execution, it is unnecessary to resolve its length property for each iteration in the loop's conditional segment. Computing its length only once and then storing it removes the length resolution from the loop's execution cycle, as demonstrated in the snippet below.

function sum(...numbers) {

    let total = 0
    const j = numbers.length

    for (let i = 0; i < j; i++) {
        total += numbers[i]
    }

    return total
}

sum(2, 4, 6) // 12

Optionally, you can make the loop a little more terse by setting the length inside the loop's variable declaration segment. The following snippet illustrates this.

function sum(...numbers) {

    let total = 0
    
    for (let i = 0, j = numbers.length; i < j; i++) {
        total += numbers[i]
    }

    return total
}

sum(3, 5, 6) // 15

The above example is admittedly of less relevance today. First, JavaScript engines have become performant to the point where there is no longer a discernible difference in performance for most applications. Secondly, since the advent of ES2015 you're more likely to see the for.. of loop as shown in the following example.

const sum = (...numbers) => {

    let total = 0

    for (const number of numbers) {
        total += number
    }

    return total
}

sum(4, 6, 7) // 18

Or by using an array convenience-method like reduce():

const sum = (...numbers) => numbers.reduce((acc, num) => acc + num, 0)

The arguments variable

Developers new to JavaScript may not be aware of the arguments variable inside the function scope. arguments is an array-like object that contains the arguments passed to a function. You can think of it as a "hybrid data structure", resembling characteristics of both an object and an array.

This special arguments variable can also be used to access arguments passed to the function that were not parameterized in the function signature.

Before JavaScript got the rest parameter (...) in the 2015 release, arguments served as the workaround for dealing with an arbitrary amount of arguments.

It's worth noting that lambda functions does not have access to this special variable. Let's take a gander at how you might use arguments in your code.

function summer() {
    let total = 0
    for (let i = 0, j = arguments.length; i < j; i += 1) {
        total += arguments[i]
    }
    console.log(total)
}

summer(5, 3, 2) // 10

Functions as default arguments

With the ES2015 specification JavaScript got native default arguments. Out in the wild you'd typically see primitives such a s a string or number, or some complex type such as an object being used as the default argument in a function signature.

However, you could also use a function as the default value for a parameter. In the following example, we'll use a function as the default argument to encapsulate the error handling to be executed when a required argument is not supplied.

function err() {
  throw new Error('square() requires an argument')
}

function square(n = err()) {
  return n * n
}

square(5) // 25
square()  // Uncaught Error: square() requires an argument

Credits
Photo by Dominik van Opdenbosch
Tags
javascript tips tricks