Short-Circuiting: And, Or, Nullish Coalescing and Optional Chaining
The &&
and ||
operators
In javascript, the && (and) operator and the || (or) operator are among the initial fundamentals we encounter while learning the language. These are also known as logical operators as they help our program decide in which direction to flow.
The and
operator returns true only when both the conditions are met and the or
operator returns true even if just one condition is met. Otherwise, they return false.
true || true -> true
false || true -> true
false || false -> false
true && true -> true
false && true -> false
false && false -> false
Apart from returning just the boolean values, these logical operators can also help us achieve short-circuiting.
Short-Circuiting
Short-circuiting is a term used for terminating a piece of the program when a condition is met and no further conditions in that program can affect the outcome of the condition met.
Short-Circuiting using the || operator
The ||
operator reads the code from left to right and searches for a truthy value. It will return the very first truthy value it finds and if no truthy value is found, then it will return the last falsy value it encountered.
Falsy values: undefined
, null
, 0
, ""
, false
, NaN
Truthy values: Rest all other remaining values.
Let's look at the example below and understand the concept through it.
/*1*/ 5 || 2 //output -> 5
/*2*/ 0 || 2 //output -> 2
/*3*/ null || false //output -> false
/*4*/ `` || `hello` //output-> hello
First example: The or
operator short circuits the program as soon as it encounters the first truthy value (5) and returns 5, without looking further for any other value.
Second Example: 0 is a falsy value and hence it further investigates the second value which is a truthy value (2) and therefore returns 2.
Third example: null is a falsy value and hence it further investigates the second value which is again a falsy value(false)
. There are no more values left to investigate and therefore it returns the last flasy value it encountered which is false
.
Fourth Example: The first value is an empty string which is a falsy value and hence it further investigates the second value which is a string hello
and therefore is considered a truthy value and the operator returns the string hello
.
To understand the concept better, think of it like this, the or
operator returns true when one of the given conditions is true. This means even if the other conditions are false, it will return true. Therefore it returns the very first truthy value it encounters.
Short-Circuiting using the && operator
The &&
operator works just opposite from the ||
operator. It returns the very first falsy value it encounters and if all the values are truthy, it returns the last truthy value it encountered.
Let's look at the example below and understand the concept through it.
/*1*/ 5 && 2 //output -> 2
/*2*/ 0 && 2 //output -> 0
/*3*/ null && false //output -> null
/*4*/ `hello` && undefined //output-> undefined
First example: The and
operator investigates the first value (5) which is a truthy value and hence further investigates the second value (2) which is again a truthy value. There are no more values left to investigate and therefore it returns the last truthy value it encountered which was 2.
Second Example: 0 is a falsy value and hence it short-circuits the execution as it returns the very first falsy value it encounters and therefore returns 0.
Third example: null
is a falsy value and hence it again short-circuits the execution and returns null
.
Fourth Example: The first value is a truthy value (hello
) and hence it further investigates the second value which is a falsy value(undefined)
and therefore returns undefined
.
To understand the concept better, think of it like this, the and
operator returns true only when all the given conditions are true otherwise it returns false. This means even if one of the conditions is false, it will return false. Therefore it returns the very first falsy value it encounters.
Nullish Coalescing Operator And Short-Circuiting
The ??
operator, also known as the Nullish Coalescing operator works very similarly to the or
operator but has a slight difference. It returns false for only two of the falsy values - undefined
and null
. For all other values, it will return true.
Let's look at an example below to understand the difference better.
//First case
0 || 1 //output-> 1
0 ?? 1 //output-> 0
//Second case
null || 1 //output-> 1
null ?? 1 //output-> 1
//Third case
false || true -> true
false ?? true -> false
//Fourth case
undefined || `Hello` //Output-> Hello
undefined ?? `Hello` //Output-> Hello
First case: The ||
operator returns 1 as 0 is a falsy value and it returns the first truthy value it encounters.
The ??
operator also returns the first truthy value it encounters. But, for this operator, 0 returns true and hence it returns 0, short-circuiting the execution of the further program.
Second case: This time, both the operators returns 1 because both of them identifies null
as false and hence they further investigate the second value(1) which is a truthy value and hence returns 1.
Third case: The ||
operator returns true
because false
is a falsy value. But the ??
operator returns false
even though it is a falsy value because it only considers null
and undefined
as false values and therefore returns false
by considering it a true value.
Fourth case: Both operators return Hello
because they both consider undefined
as false and therefore investigates the second value (hello
) which is a truthy value and hence returns hello
.
Optional Chaining (?.)
Optional chaining also short-circuits the further execution of a piece of code but its use is related to objects. We use optional chaining while accessing a property of some object that we are not sure exists.
In general, when we access a property of an object using the dot notation and that property is not existing, it returns undefined
. But if we access the property of a non-existing property of an object, we will get an error.
Let's look at an example.
const snacks = {
chocolates: [`Snickers`, `Lindt Bar`, `Cadbury Dairy Milk`],
chips: [`Lays`, `Cheetos`, `Tagz`]
}
console.log(snacks.drinks);
//Output
undefined
Here, when we try to access the property drinks
of the object snacks
we get undefined
as the output because that property does not exist.
console.log(snacks.drinks.cold);
//Output
`Uncaught TypeError: Cannot read properties of undefined (reading 'cold')`
But when we try to access the property cold
of the property drinks
that is already not existing, we get a type error.
This is because javascript considered that non-existing property (drinks
) to be undefined. And then we tried to access a property of undefined
which is not possible and hence we end up getting an error.
Now, imagine if we were trying to access some data from some server using some API. We are not sure if a property is existing on that server, in this case, if the property is not existing and we try to access it, we may end up getting an error and our program will not run. Therefore, we apply the concept of optional chaining here.
Short-circuiting using the ?.
operator
We can short-circuit a program using optional chaining so whenever a property is undefined
and we are further accessing the property of the undefined
property in our code, the ?.
operator will short-circuit the program at the point where the property was considered undefined
and return undefined
as the output instead of throwing an error.
Consider the example below for a better understanding.
const snacks = {
chocolates: [`Snickers`, `Lindt Bar`, `Cadbury Dairy Milk`],
chips: [`Lays`, `Cheetos`, `Tagz`]
}
console.log(snacks.drinks);
//Output
undefined
console.log(snacks.drinks.cold);
//Output
`Uncaught TypeError: Cannot read properties of undefined (reading 'cold')`
//Using Optional Chaining
console.log(snacks.drinks?.cold);
//Output
undefined
As you can observe, we used an ?
after the property drinks
in the above code and instead of an error, we got undefied
as the output. This is because we used the optional chaining operator on the property we were not sure about the existence of.
Hence, as soon as that property was considered undefined, our program short-circuited and did not access further properties of that undefined
property and the result was undefined
.
Although, if drinks
were an existing property, our program would execute normally.
const snacks = {
chocolates: [`Snickers`, `Lindt Bar`, `Cadbury Dairy Milk`],
chips: [`Lays`, `Cheetos`, `Tagz`],
drinks: {
hot: [`chocolate milk`, `vanilla milk`],
cold: [`coke`, `fanta`]
}
}
//Using Optional Chaining
console.log(snacks.drinks?.cold);
//Output
['coke', 'fanta']
Using Optional Chaining And Nullish Coalescing Together
We can combine optional chaining and the nullish coalescing operator together so that whenever we get undefined
through optional chaining, we can assign another piece of code to be executed in that case.
Look at the example below.
const snacks = {
chocolates: [`Snickers`, `Lindt Bar`, `Cadbury Dairy Milk`],
chips: [`Lays`, `Cheetos`, `Tagz`]
}
//Using Optional Chaining and Nullish Coalescing Together
console.log(snacks.drinks?.cold ?? `There are no drinks :(`);
//Output
`There are no drinks :(`
Here, the optional chaining returns undefined
and the nullish coalescing operator then considers it as a false value and investigates the second value which is a string and hence returns the string There are no drinks :(
.
Summary
Let us summarise what we have learned in this blog.
First, we understood that short-circuiting is the process of terminating a program once a condition is met and no further conditions can change the program's outcome.
Then we learned about types of operators that can perform short-circuiting.
The or(||
) operator: Returns the first truthy it encounters otherwise returns the last falsy value it encountered.
The and(&&
) operator: Returns the first falsy it encounters otherwise returns the last truthy value it encountered.
The Nullish Coalescing(??) operator: Works similar to the or operator but returns false only for undefined
and null
values.
Optional Chaining(?.): Works with objects and is used when we are not sure about the existence of a property. When the property, on which the operator was used, is not existing, optional chaining returns undefined
by short-circuiting the piece of code. We can use a nullish coalescing operator with optional chaining to return another value in case optional chaining short-circuits the program.
Subscribe to my newsletter
Read articles from Pranav Patani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by