ES2020 NULLISH COALESCING OPERATOR
The nullish coalescing operator is a new logical operator. Behind the strange name is an important new feature, an interesting operator in ES2020, and a great addition to JavaScript.
One of the most common practices for setting a variable’s default value is by using the OR (||) operator. For example:
let myVar = undefined;
let a = myVar || 'default value';
console.log('a', a); // default value
Here we’re giving a new value to the variable a. The variable’s value depends on myVar. If it’s defined the a will take its value. But if it’s undefined then it takes the default value.
This also works will null:
let myVar = null;
let a = myVar || 'default value';
console.log('a', a); // default value
The problem is, no matter whether the value is an empty string, 0, or false, we’ll get the same behavior as if it were undefined\null. For example:
let myVar = 0;
let a = myVar || 'default value';
console.log('a', a); // default value
Or:
let myVar = '';
let a = myVar || 'default value';
console.log('a', a); // default value
And this can be ultra problematic. Why? Because often in our applications, the values 0, false, or an empty string are legitimate values that serve a purpose. Think about a user object that I get from the server where I use only some of the parameters in some component. I don’t know if those values exist at all in that object.
Here’s a very relevant example, taken from the TC39 draft proposal. The values I’m getting from a distant object for user settings are relevant, and still it’s taking the default values! Because as far as the || is concerned, legitimate values like 0 or false are considered to be undefined\null.
const response = {
settings: {
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const headerText = response.settings.headerText || 'Hello, world!';
const animationDuration = response.settings.animationDuration || 300;
const showSplashScreen = response.settings.showSplashScreen || true;
console.log('headerText', headerText); // Potentially unintended. '' is falsy, result: 'Hello, world!'
console.log('animationDuration', animationDuration); // Potentially unintended. 0 is falsy, result: 300
console.log('showSplashScreen', showSplashScreen); // Potentially unintended. false is falsy, result: true
Why? Because the || operator is a logical operator that evaluates whatever it receives and returns the values that are not interpreted to be false. As all JavaScript programmers know, 0 or false are entirely false. In the eyes of the || operator, an empty string or even NaN is kind of a falsy result that will always return whatever comes afterward or false.
To solve this problem we now have the new operator nullish coalescing. This operator, which looks like this: ??, works just like || but interprets only undefined or null as false. This means the problem is totally gone:
const response = {
settings: {
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;
console.log('headerText', headerText); // ''
console.log('animationDuration', animationDuration); // 0
console.log('showSplashScreen', showSplashScreen); // false
I don’t see any reason not to use this operator instead of || when setting a default value. At the moment, it doesn’t work in browsers, but the emphasis is on “at the moment.” But, like with so many other features, if you’re using Babble, which you should be, then it’ll work just fine. Here’s a Codepen where you can see it in action:
About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment