Short-circuit evaluation in JavaScript

When I was first learning JavaScript, I learned about the usual conditional statements pretty quickly: the if...else statement, the switch statement, and even the ternary operator. But it was a little while before I learned about short-circuit evaluation. Let’s dig into it!

Short-circuit evaluation is a way to take advantage of certain logical operators to make your code more efficient. As explained on the MDN Web Docs:

As logical expressions are evaluated left to right, they are tested for possible “short-circuit” evaluation using the following rules:

  • (some falsy expression) && expr is short-circuit evaluated to the falsy expression;
  • (some truthy expression) || expr is short-circuit evaluated to the truthy expression.

Short circuit means that the expr parts above are not evaluated, hence any side effects of doing so do not take effect (e.g., if expr is a function call, the calling never takes place). This happens because the value of the operator is already determined after the evaluation of the first operand.

Let’s look at a really common example, and then a more contrived one just to help further illustrate the point.

Default function parameters

Some programming languages allow you to define default parameters for your functions. They let you initialize parameters with default values if no value or undefined is passed in as an argument. They were only added to JavaScript in ES6 (ES2015), though, so they have no IE support whatsoever.

/**
 * Log a person's name to the console
 */
function logName (name = "Kieran") {
  console.log(name);
}

// Logs the argument ("Amelia")
logName("Amelia");

// Logs the default value ("Kieran")
logName();

In the example above, I set the string "Kieran" as the default value for the name parameter. When I call the function without passing in an argument (meaning name is undefined), "Kieran" is the value used.

If you wanted to support IE, you could use a transcompiler like Babel. I don’t like to complicate my process with tools like that, so I’d just use short-circuit evaluation. Here’s how I’d rewrite the previous example.

/**
 * Log a person's name to the console
 */
function logName (name) {

  // Set a default value for the name parameter
  name = name || "Kieran";

  // Log the name to the console
  console.log(name);

}

This rewritten logName() function behaves in exactly the same way, now with IE support, thanks to the use of short-circuit evaluation. It works because, as explained above, (some truthy expression) || expr is short-circuit evaluated to the truthy expression.

That is: if a non-empty string is passed in, the name parameter becomes truthy, and so the rest of the statement is skipped.

If nothing is passed in, the name parameter becomes undefined, which is falsy. The value "Kieran" gets used instead because it’s truthy.

Checking if an element exists before using it

When selecting an element from the DOM, it’s a good idea to make sure it actually exists before trying to use it. Otherwise, your script will throw a TypeError. Here’s a simple example…

// Get an element that doesn't exist
var sandwich = document.querySelector("sandwich");

// Try to set its textContent
sandwich.textContent = "🥪";

// Output:
// TypeError: document.querySelector(...) is null

In the script above, I try to select a sandwich element. This doesn’t exist in the DOM (it’s not a valid element name), so the .querySelector() method returns null. The .textContent property is only available to the Node interface, so trying to access it on null returns the TypeError.

To avoid this error, I’d usually wrap the reference to the sandwich variable inside an if statement:

if (sandwich) {
  sandwich.textContent = "🥪";
}

It’s worth knowing, though, that you can do this using short-circuit evaluation. You’ll often see it in code that’s been run through a minifier like Terser. Here’s what the previous example would look like:

// Get an element that doesn't exist
var sandwich = document.querySelector("sandwich");

// Try to set its textContent
sandwich && (sandwich.textContent = "🥪");

// No error! 🙌

Pretty cool, right? The value of the first operand is null, which is falsy, so the rest is skipped and never runs. Note that the parentheses are necessary here, otherwise you’d get a SyntaxError like so:

SyntaxError: invalid assignment left-hand side

In practice, I would just use the if statement because it’s more readable. But it’s useful to know about, and hopefully this extra example helps to illustrate how short-circuit evaluation works.


If you have questions, feedback, or any other suggestions, please do email me. I'd love to hear from you!