My app behaves abnormally and figured the code below is going to else statement unexpectedly.
code
if(" " != 0) {
console.log("whitespace is not zero");
}
else {
console.log("bar");
}
Firebug output
bar
I thought whitespace is a String and comparison against integer zero should return false like the case above but I don't know why it is going to else statement.
Could anyone explain why?
In JS, " " == 0
equals true
with loose/lenient comparison, you should use strict equality operator ===
/!==
instead:
" " !== 0
To get to first condition.
Tests:
console.log(" " == 0); // true
console.log(" " === 0); // false
Loose Comparison Chart:
"" == "0" // false
0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true
Strict Comparison Chart:
"" === "0" // false
0 === "" // false
0 === "0" // false
false === "false" // false
false === "0" // false
false === undefined // false
false === null // false
null === undefined // false
" \t\r\n" === 0 // false
(Examples by Douglas Crockford)
Good Practice:
Whenever possible, use strict equality operator because with loose equality operator, JS does type coercion which is a performance hit and doesn't always yield expected results as shown in above comparison charts.
When you use !=
rather than !==
, JavaScript tries to coerce the values on either side to the same type. In this case, I think it converts both to numbers.
" "
happens to be 0
as a number. (Try " " * 1
. It evaluates to 0
.)
This also works with other operators like >
or *
. So " " > -1
is true and " " * 100
is 0
. This also means you can do neat stuff like "6" * "7"
and get 42
. Unfortunately, this breaks down with +
since it is inexplicably overloaded to do both math and string concatenation.
I personally like all of this behavior except for +
. Others' opinions vary.
The other answers have told you how to solve the issue. My answer will attempt to actually explain why you have the issue in the first place (since that was your actual question!)
The behaviour of the ==
operator is defined in the spec as the "abstract equality algorithm". It states (among other things) the following:
If Type(x) is String and Type(y) is Number, return the result of the
comparison ToNumber(x) == y.
One of the rules of the ToNumber
operation on a string is as follows:
The MV of StringNumericLiteral ::: StrWhiteSpace is 0...
Once the exact MV for a String numeric literal has been determined, it is then rounded to a value of the Number type. If the MV is 0, then the rounded value is +0 unless the first non white space character in the String numeric literal is ‘-’, in which case the rounded value is −0.
So we are left with +0 == 0
which fits another rule of the abstract equality algorithm:
If x is the same Number value as y, return true.
This is the case because 0
is the same as +0
. Even if one of the numbers was -0
it would return true:
If x is +0 and y is −0, return true.
If x is −0 and y is +0, return
true.
to compare with the number 0, you must use the strict comparison ===
if(" " !== 0) {
console.log("whitespace is not zero");
}
else {
console.log("bar");
}
a "truth table" found here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
because a string with whitespaces is converted to 0. So
To compare:
if(" " !== 0) {
....