My go-to has always been the ternary operator for assigning a value to a variable conditionally. But ever since I discovered that โ||โ can be used as a selector operator, Iโve been using that more. I find my code so much easier to read ๐
Yes, it takes some time to wrap your head around it. But once you grasp the concept, itโs super handy. Now I donโt think less code makes your code better. But in this instance, I prefer the ||
operator ๐คฉ
let isHappyHour = '๐บ';
// Logical Operator
isHappyHour = isHappyHour || '๐ต'; // '๐บ'
// Ternary
isHappyHour = isHappyHour ? isHappyHour : '๐ต'; // '๐บ'
// If/Else
if (isHappyHour) {
isHappyHour = isHappyHour
} else {
isHappyHour = '๐ต'
}
console.log(isHappyHour); // '๐บ'
Understanding the ||
Operator
I'm sure most of you thought the ||
is only used for boolean checks like this:
if(a || b) {
// do something
}
BUT! You can also use it to evaluate the selected expression and produce a value. And that's why it's helpful to think of the logical operator as also a selector operator. When it's used with non-boolean values, the ||
operator will return a non-boolean value of one of the specified expression or operands.
Head explosion yet?! No worries, let me explain it the way Kyle Simpson explains it. He is the author of "You Don't Know JavaScript" - a free JavaScript e-book.
The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.
Alright, let's look at an example.
const truthy = true;
const falsy = false;
const poop = '๐ฉ';
truthy || poop; // true
falsy || poop; // '๐ฉ';
As long as the 1st expression (left side) is truthy, it will always be the one selected. However, if the 1st expression (left side) is ever falsy, then the 2nd expression (right side) will be by default output. And that's why this ||
is known as the operator to set default values.
Using Default Value as Function Parameter
Quite often you would see ||
being used like this:
function(name) {
name = name || 'no name';
}
Note: this is not the recommended way anymore. It's way better to ES6's default parameters. Because quite often, you might not want the default to kick in for ALL falsy values -- I'll explain falsy values in the next section. Most likely, we only want the default value to be set if no value or undefined
is passed as the argument.
The better solution with ES6 Default Parameters
function(name = 'no name') {
}
Falsy Values
In the ||
operator, the 2nd expression (right side) is only evaluated IF the 1st expression (left side). So let's check what constitutes a falsy value.
// JS Essentials: Falsy Values
false
undefined
null
NaN
0
"" or '' or `` (empty string)
```
<br>
_(I wrote another blog post on Falsy Values, which you can read it [here](https://www.samanthaming.com/tidbits/25-js-essentials-falsy-values))_
## Compared to the `&&` operator
In my previous post, I wrote about the `&&` operator. (Read it [here](https://medium.com/@samanthaming/prevent-object-retrieval-typeerror-with-74ea0a58437f)). The `&&` is also known as the **Guard Operator**. So here's a quick summary of the difference:
- `||`: 1st expression is always outputted. The 2nd expression only gets outputted if the 1st expression is falsy.
- `&&`: 1st expression is outputted if it's FALSY. The 2nd expression only get outputted if the 1st expression is truthy.
## What is the Elvis Operator
This is an interesting one. In JavaScript we have `||` to set default values. In other languages such as **C++**, this behavior is similar to the **Elvis Operator** which is denoted as `?:`.
```javascript
// JavaScript
someVariable || 'default value'
// Elvis Operator (not JavaScript)
someVariable ?: 'default value'
```
As to why it's called the Elvis Operator:
![Credit to GlobalNerdy.com](https://thepracticaldev.s3.amazonaws.com/i/7itmzmaoim6awjmqop4k.jpg)
_Image Credit to GlobalNerdy.com_
## When to use which?
Now that you understand **Falsy Values**, let's figure out which way of the 3 ways is better to use.
**๐Logical Operator `||`**
This is great if you want to capture all falsy values. It's less code and it's way easier to read. Assuming that everyone understands all 3 behaviors, of course.
_NOTE: I'm not saying less code is always better, one can easily try to be too clever and shorten the code which renders it unreadable. We write code for others, it's a form of communication. It's always better to go with the option that conveys understanding over being clever._
```javascript
let a;
// โ
Short and simple
a = a || b;
// โน๏ธ Meh, could be better
a = a ? a : b;
// ๐ฑ Ouch
if (a) {
a = a;
} else {
a = b;
}
```
**๐Ternary Operator**
Let's say we don't want to capture ALL falsy values. And we only want the default value to kick in when it's `undefined`
```javascript
// โ Logical doesn't work
a = (a === undefined) || b;
// (a === undefined) > will output a boolean 'true' not the actual value
// โ
Ternary works
a = (a === undefined) ? a : b;
// โน๏ธ Of course if/else will also work...but Ouch
if (a === undefined) {
a = a;
} else {
a = b;
}
```
**๐If/Else**
This is the option with the MOST control. And it's something I would absolutely go for if say, I need to perform an additional action.
```javascript
// โ
If/Else is much better
if (a) {
a = a;
// do something else
} else {
a = b;
}
```
---
## Resources
- [MDN Web Docs - Logical Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/)
- [YDKJS: Types & Grammer](https://github.com/getify/You-Dont-Know-JS/blob/f0d591b6502c080b92e18fc470432af8144db610/types%20%26%20grammar/ch4.md)
- [Wikipedia - Elvis Operator](https://en.wikipedia.org/wiki/Elvis_operator)
- [Stack Overflow - Comparison of Ternary operator, Elvis operator, safe Navigation Operator and logical OR operators](https://stackoverflow.com/questions/44046927/comparison-of-ternary-operator-elvis-operator-safe-navigation-operator-and-log)
- [Stack Overflow - Logical or vs. Ternary operator](https://stackoverflow.com/questions/42026158/precedence-logical-or-vs-ternary-operator)
- [Default Operator in JavaSctipt and Real Life Examples](https://zzz.buzz/2016/01/10/default-operator-in-javascript-and-real-life-examples/)
- [SamanthaMing.com - Guard Operator](https://www.samanthaming.com/tidbits/51-prevent-object-retrieval-type-error-with-guard-operator)
---
**Thanks for reading โค**
Say Hello! [Instagram](https://www.instagram.com/samanthaming/) | [Twitter](https://twitter.com/samantha_ming) | [Facebook](https://www.facebook.com/hisamanthaming) | [Medium](https://medium.com/@samanthaming) | [Blog](https://www.samanthaming.com/blog)
Top comments (6)
We can make a helper function
Just beware of when you have an original value which is falsey, for example, I recently had to get a numeric value from either the body of a request or the query string, using swagger. Swagger, since it was informed that the value would be numeric, had already populated the model with a numeric value.
So I had code (kinda) like this:
The problem was that the value in the swagger body object was zero, so it was falling over to attempt to get the value from the query, where it didn't exist, so the final result was
undefined
! This caused me a bit of a puzzlement, and I had to rather use:So if you're using
||
, just watch out for valid falsey values: if you can use empty string, zero or an actualfalse
as a value, don't use||
(:Yes! โ||โ will capture ALL falsy values listed in the article. Definitely something to be really mindful of. Thanks for sharing your example and emphasizing that point! Very important and a very common gotcha that can cause extreme headaches ๐ต
Given that your "ouchy"
if
/else
s are only checking for truthiness, you'd miss out thea = a;
part in the real world, though.becomes just this:
and copes with specific tests like:
and that doesn't seem long or awkward to me; it seems explicit and readable.
Personally, I like the Elvis style (though it looks more like Jonny Bravo to me...) or the null coalescing operator you have in other languages (like SQL and nowadays even PHP), which has the benefit of being chainable like the
||
method.The code in this segment is backwards - you're setting
a
toa
only if it isundefined
, and using b in all other cases.Nice article, I would love to see the Elvis operator in Javascript!
Another way you can assign default values is with Proxy. This can be done explicitly, implicitly, on a per-type basis, etc.