Comparing Undefined Values With Optional Chaining In JavaScript
Yesterday, while working on some HTMX experiments, I stumbled upon a feature of JavaScript that I didn't known: the undefined
value, when compared to Booleans and numbers, always returns false
. I've always thought of undefined
as a falsy value (which it is); so, I was very surprising to see that undefined
did not soft equal false
. But, this turns out to be hugely beneficial when it comes to the optional chaining operator (aka, the safe navigation operation) in JavaScript.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
First, let's just run a test to see how the undefined
value behaviors. In the following script, I'm going to evaluate a number of statements in which we compare undefined
to various Booleans and numbers:
var comparisons = [
"undefined == false",
"undefined == true",
"undefined == 0",
"undefined > 0",
"undefined >= 0",
"undefined < 0",
"undefined <= 0",
];
for ( var test of comparisons ) {
console.group( `Testing: %c${ test }`, "color: red" );
console.log( `%c${ eval( test ) }`, "background: yellow" );
console.groupEnd();
}
I'm iterating over the statements and evaluating each one of them using eval()
. And, when we run this JavaScript code, we get the following output:

As you can see, each one of these JavaScript comparisons to undefined
results in false
.
This was the surprising behavior (to me). I had always just assumed that undefined
would be soft equal to false
(it is to null
, by the way). But, the fact that undefined
results in a false
comparison becomes very helpful in the context of the safe navigation operator.
Consider the following expression:
data.optionalInput.indexOf( "x" ) >= 0
In this case, if optionalInput
is undefined
, this expression will throw a null reference error (NRE) because .indexOf()
is not a valid method on undefined
. We can combat this by including the safe navigation operator prior to the method call:
data.optionalInput?.indexOf( "x" ) >= 0
Now, if the optionalInput
property is undefined, the expression will short-circuit and evaluate to undefined
; which leaves us with this comparison under the hood:
undefined >= 0
Historically, I've always assumed that this would result in true
since I always assumed that undefined
would match on the = 0
part of the >= 0
comparison. But, as we've demonstrated above, the undefined
value always results in false
when compared to numbers. Which means this:
undefined >= 0
... results in false
!
This JavaScript behavior can simplify our if
blocks when it comes to things lie the indexOf()
comparison. Consider this workflow:
var inputs = {};
// Note: "value" is an undefined property.
if ( inputs.value?.indexOf( "hello" ) >= 0 ) {
console.log( "Hello Found!" );
} else {
console.log( "Hello Not Found" );
}
With my old assumptions about the JavaScript behavior, I would have expected the comparison to result in true
since I, again, had historically assumed that the undefined
value produced by the safe navigation operator (short-circuiting the left-hand expression) would have matched on 0
. But, it doesn't! Which means that when we run the above JavaScript code, we get the following log:
Hello Not Found
This is awesome! It means that I don't have to dance around the possibility of an undefined value in my if
conditions. Unless I'm explicitly comparing it to null
or undefined
, I can safely use undefined
values (and more specifically, I can safely use the optional chaining operator) without accidentally entering my "truthy block".
I can't believe I didn't know this about JavaScript! It's going to make a few types of scenarios easier to code.
And, to be clear, my historical assumption isn't that crazy. After all, this comparison:
false >= 0
... does result in true
(since false
soft equals 0
). And, in my mind, false
and undefined
were roughly equivalent. It was my bad to assume this; but, it's not like I was just making it up out of thin air - it was based on some degree of reasonable logic. My logic just happened to be built on incorrect facts.
Learning for the win!
Want to use code from this post? Check out the license.
Reader Comments
JS always has surprises! Glad this helped simplify your code, those little discoveries are the best.
100% it's just satisfying to feel like I'm always building a better understanding of the fundamentals.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →