Content:
Comparisons are a key part of any application. Whether an if statement or a switch-case statement, it’s almost certain you’ll use them at some point in your code.
It’s therefore useful to learn a few of the JS comparison quirks waiting to trip you up. It’s likely that you’ll encounter at least one of these in your code at some point, and it can be very difficult to diagnose and rectify.
Falsy 0
If you’re comparing integers, be mindful of the impact of a value of 0 or 1. Consider the following code.
let shippingCost;setShippingCost(cost) => {
this.shippingCost = cost;
}
It’s a basic function, which sets a shippingCost
variable to the value passed to the function.
Let’s add a bit more code, to use our shipping cost.
if (this.shippingCost) {
return this.shippingCost;
} else {
return '5.00';
}
This code will either give us the shippingCost
value, if it’s been set, or a default value of ‘5.00’ if it isn’t. A shopping website could use code like this to set a flat shipping fee by default, but override it for selected orders – for example, when spending over a certain amount.
The if
statement checks the value of shippingCost
. If it hasn’t been set, this will return false
, and ‘5.00’ will be returned. It’s the same as writing
if (this.shippingCost == true)
To perform this comparison, this.shippingCost
will be converted to a boolean, due to type coercion. A non-zero value will be converted to true.
But what if the value had been set to 0?
if (this.shippingCost == true)
When converted to a boolean, a value of 0 equates to false
giving us
if (false == true)
This equates to false
, meaning we fall into the else
clause. This means a value of ‘5.00’ will be returned, despite us explicitly passing in a value if 0.
This can be a tricky one to spot. If you’re setting the value you want, it would be easy to overlook the impact of setting a value of 0. For this reason, it’s important that a simple true/false comparison is not relied upon, when dealing with integers.
Instead, if you need to check whether a value has been set, use typeof
.
if (typeof this.shippingCost !== undefined)
If a variable has not been given a value, it will have a type of undefined
. By checking for this type, you can differentiate between variables that have no value, and those which have a value which equates to a boolean false
.
Depending on the example, you could also use ===
rather than ==
. This prevents the type coercion which converts our 0 to false
, requiring the data type on each side of the comparison to also match to return true
.
Falsy ”
A follow on from the previous section, but this time with an empty string (or ”).
” exhibits the same behaviour as 0, being coerced to false
during a comparison with a boolean. Strings that are not empty will be coerced to true
.
This one can actually be useful – I’d imagine you’re far less likely to be trying to do something intentional with an empty string.
Conversion to Character Codes
Another comparison quirk arises with strings that represent integers.
Take the following example.
if ("90" > "100") {
print("Wait what?")
} else {
print("Of course it's not")
}
If we were comparing integers, the if statement would of course evaluate to false. This would also be true had just one of the two values been an integer – the other would be coerced to an integer for the comparison.
Two strings? They’ll be evaluated as if they’re strings. Due to both being the same type, no coercion will take place. Just because we can see they both look like integers, doesn’t mean they’ll be treated as if they were integers.
Instead, the standard string comparison takes place. String comparisons are done using ASCII character codes. Each character is converted to the corresponding ASCII character code in turn, and compared with the character code for the other string.
So in this case, we have:
- “90”: 9 – character code 57
- “100”: 1 – character code 49
As character code 57 is greater than character code 49, “90” is deemed to be greater than “100”.
Null Does Not Equal undefined…Unless it Does
The types null
and undefined
have a curious relationship with one another.
JavaScript allows the creation of variables, without giving them a value.
let x;
If we check the type of x
…
typeof x;
>> undefined
we get the type undefined
. A variable that hasn’t been given a value will always be undefined
.
In comparison, null indicates that there is no value – but has been explicitly defined this way.
let x = null;
typeof x;
>> null
Given that null and undefined are two separate types, you might expect a comparison of the two to return false
.
console.log(undefined === null);
>> false
You’d be correct – a strict comparison returns false. But what if we use the less string comparator?
console.log(undefined == null);
>> true
There’s no fancy explanation to this one – it’s simply a quirk of JS. It’s worth remembering if you’re planning to differentiate between null
and undefined
variables.