DEV Community

Cover image for Question mark features in JavaScript
Kevin Beltrão
Kevin Beltrão

Posted on • Edited on

Question mark features in JavaScript

Table of Contents

  1. Introduction
  2. Ternary
  3. Optional Chaining
  4. Nullish Coalescing Operator
  5. Logical Nullish Assignment

Introduction

JavaScript has some pretty helpful features that use ? in the syntax, but they don't necessarily have much in common besides the question mark. In this article, my goal is to show you cool tricks, starting with a well-known (and also present in other languages, which is the ternary) and going through some less known operators.

If you want to find more about me, @kevbeltrao on Instagram, Youtube, Github, Linkedin, etc. Or simply kevbeltrao.com.br.

Ternary

Ternary is basically a different way to write an if/else statement. The regular if/else statement is represented like:

if (condition) {
  actionIfTrue();
} else {
  actionIfFalse();
}
Enter fullscreen mode Exit fullscreen mode

I like to think of the ternary as a question, so if I want to ask "is it a panda?" I need that question mark. After the question, I need the return options of the ternary (the option if the condition is true and the option if false), which will be separated by a :

isPanda ? actionIfTrue() : actionIfFalse() // We're asking if isPanda is true/truthy
Enter fullscreen mode Exit fullscreen mode

And as pointed out, you choose the return value of the ternary. It's an expression, so you can use it for a value assignment, for example:

const animalColor = animal === 'panda' ? 'white' : 'blue';
Enter fullscreen mode Exit fullscreen mode

And of course you can nest ternaries (which I strongly discourage due to its loss of readability):

const animalColor = animal === 'panda' ? 'white' : animal === 'crocodile' ? 'green' : 'blue';
Enter fullscreen mode Exit fullscreen mode

Which has the same effect as in:

let animalColor;

if (animal === 'panda') {
  animalColor = 'white';
} else if {
  animalColor = 'green';
} else {
  animalColor = 'blue';
}
Enter fullscreen mode Exit fullscreen mode

Optional Chaining

Optional chaining is one of the most awesome features in JavaScript, it helps us with value checking if values are undefined using a shorter syntax. First of all, I'll show you what you should be afraid of:

const person = {
  address: {
    streetName: 'JS Ave',
  }
};

getCityPhoneCode(person.address.city);
Enter fullscreen mode Exit fullscreen mode

In this case, we are trying to access city within address, which doesn't exist. No problems so far, the application won't crash by that (unless getCityPhoneCode expects a valid value), but we are sending the value undefined as an argument. So, in JavaScript, if you try accessing an unexisting value from an object you get undefined. Keep that in mind!

But what if our code was:

const person = {};

getCityPhoneCode(person.address.city);
Enter fullscreen mode Exit fullscreen mode

In this case, our application would crash because we are not trying to access an unexisting property from an object anymore, but from undefined. The problem here is that address is undefined, so we can't do undefined.city. Since there's a chance of address being undefined, we'd have to be extra careful and usually make a simple check before:

if (person.address) {
  getCityPhoneCode(person.address.city);
}
Enter fullscreen mode Exit fullscreen mode

But JavaScript now provides us optional chaining, which would look like that:

const person = {};

getCityPhoneCode(person.address?.city);
Enter fullscreen mode Exit fullscreen mode

So if address is null/undefined, we'll instantly get undefined returned instead of having our app crashing trying to access city. We can also have multiple checks:

person?.eyes?.color?.hex;
Enter fullscreen mode Exit fullscreen mode

And if either person, eyes, or color is null/undefined, undefined is returned and our code is protected from the error cannot read properties of undefined.

Nullish Coalescing Operator

Nullish Coalescing Operator looks scary but is even simpler than the previous ones. To simplify, the question you want to make is "is this value either null or undefined?" if so, return the next one (it'll get easier with examples):

null ?? 1 // 1
undefined ?? 'Hello, World' // 'Hello, World'
0 ?? 4 // 0
false ?? 3 // false
Enter fullscreen mode Exit fullscreen mode

It's often compared to the || (or) operator, which returns the first truthy value (or the last value if neither are truthy):

null || 1 // 1
undefined || 'Hello, World' // 'Hello, World'
0 || 4 // 4
false || 3 // 3
Enter fullscreen mode Exit fullscreen mode

Let's say you want to send the price for a function, but the price might be undefined and if so, the product is free. What you wanna do is:

applyDiscount(price ?? getPrice());
Enter fullscreen mode Exit fullscreen mode

And this way, if price is 3.59, we'll send this value as an argument. In case price is null/undefined, we're calling getPrice and sending its return to applyDiscount.

Logical Nullish Assignment

If you got the last one, this one uses pretty much the same logic. Do you know when you want to assign a value to a variable but only if it hasn't already been done? Here's what it'd look like:

price ??= 0;
Enter fullscreen mode Exit fullscreen mode

What we are saying is: assign 0 to price, but only if its value is null/undefined.

In other words, it's a way of making sure you're only assigning a value if the variable doesn't have one yet.

Top comments (1)

Collapse
 
debespindola profile image
Deborah Espíndola

This is very interesting and usefull! I didn't know about the last one and I'll be using a lot.