Quickie Dev #1: About falsy and default values in Javascript

Because setting default values in Javascript can seem very simple… until you realize you can’t actually override them!

Mina Pêcheux
Mar 4 · 5 min read

When you write code, you want your variables to have clearly defined values, you want to know what they are equal to at any given point in your program. The easy case is when you explicitly set a variable: if you say that a = 2, then the value of a is 2 (obviously). But what about variables you haven't explicitly set? (Or haven't explicitly set yet?) Those variables still have their default value.

The problem

There are various ways of initializing a variable and plenty of articles on the net to give you some shorthands. In Javascript, a well-known technique is to use the logical “or” operator, ||, to override the default value when you initialize a variable. This is particularly neat when you have some default configuration and you want to override it with user-specific options.

For example, let’s say I’m writing a program to display geometric shapes. The idea is to show a square, a triangle and a circle on a row, either black or red, that are evenly spaced out. I have two settings I can tweak: the spacing between the shapes and a useBlack flag to tell whether to draw black or red shapes.

We can set the spacing between the shapes and the color used to draw them (black or red).

Now, most of the time, I want the shapes to be black and the spacing to be of 10 pixels. In order words, I can define my basic configuration as:

var config = {
spacing: 10, // in pixels
useBlack: true
}

And in my program, I’ll just use this configuration when calling my drawing logic:

var config = {
spacing: 10, // in pixels
useBlack: true
}

function run() {
const spacing = config.spacing;
const useBlack = config.useBlack;
// the magic functions that draw my shapes
setShapesSpacing(spacing);
setPaintColor(useBlack);
drawShapes();
}

run();

This works great! Now it’s time to add my user-custom variables: this time I want to draw shapes with a 2 pixels-spacing, so that they’re closer together. To do this, let’s create a second object to hold our user configuration and use the famous || operator that allows you to easily assign a value to a variable from a list of possible sources.

function run(options) {
const spacing = options.spacing || config.spacing;
const useBlack = options.useBlack || config.useBlack;
...
}
run({ spacing: 2 });

As you can see, you write the default value on the far right and then the possible override on the right, and we separate the two with the || operator. So you need to read this from right to left to get the real re-assignment order.

When I run this code, shapes are indeed closer together, yay!

Problem: However, if I decide to set a 0 pixel-spacing, then shapes suddenly jump back to their original position. Similarly, if I try and use the same technique for my colors by adding a useBlack set to false, nothing changes!

The why

This is because the || operator is actually returning the “first non-falsy operant”, or in other words the first value in your series of possibilities that is not considered “false” by Javascript. And there actually are more falsy values than we might think...!

When you pass in “0” or “false” as I just did, then this value is actually a falsy, so our initial base-configuration default will naturally pop up and our user-custom config will be ignored.

Note: as a rule-of-thumb, you can remember that using a falsy value with the || operator never returns the falsy value, and using a falsy value with the && operator always returns it.

Some solutions

To fix our problem, we have several possibilities.

Object.assign()

This allows you to completely overwrite the key-value pairs of an object. You start from a source and you “add on” one or more targets that may or may not share the same keys as the source:

const result = Object.assign(targetC, targetB, targetA, source);

Every time the same key is encountered, the program will simply overwrite the value. Else if there is a new key, it will be added to the final object with its new value. If none of the targets contain a key that is present in the source, then this key-value pair will be left unchanged.

Similarly to our previous example with the || operator, when using Object.assign you need to read the overwrites from right to left:

Using the ?? nullish coalescing operator (ECMA 2020)

Warning: this operator is only available if you are using Javascript ECMA 2020 or later.

The big difference between the ?? and the || operator is that the ?? operator only ignores the left operant if its is equal to null or undefined, instead of any falsy value. So a user-custom value of 0, an empty string or even NaN will not be skipped with this operator:

const spacing = options.spacing ?? 10;
// -> if options.spacing = 2, spacing = 2
// -> if options.spacing = 0, spacing = 0
// -> if options.spacing = null, spacing = 10

Reverting to a basic condition

If you’re unsure of your data or you’re afraid it might do something unexpected, you can always revert to an explicit condition (either with an if/else statement or with a ternary condition):

let spacing = 10;
if (typeof options.spacing === 'number') {
spacing = options.spacing;
}
let useBlack = options.useBlack === false ? false : true;

Note: be careful, you might be tempted to use !options.useBlack… but this will lead to the exact same issue as with the || operator since the ! operator checks for falsy values too.

To conclude

Javascript is famous for being a somewhat “implicit” language that often does quite weird things until you understand the underlying reasons. Since JS is not a typed language, using the logical or coalescing operators properly to set default values requires you to really know your data, the types of your variables and the values they can take. Still, when used correctly, they are both very powerful tools.

If you liked this article, you can find more blog posts about tech, AI and programming on my website :)

Nerd For Tech

From Confusion to Clarification

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store