2

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?

Meow
  • 18,371
  • 52
  • 136
  • 180

5 Answers5

8

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.

Camilo Martin
  • 37,236
  • 20
  • 111
  • 154
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
  • So whenever possible means I should be even using strict comparison for comparing thing like index? ex: if(index === someString.length) I mean here I'm sure both are number though. – Meow Feb 16 '12 at 08:30
  • @masato-san: Strict compartion not only compares `value` but also `type` of both operands. So when you are sure about `type` of both, you can go ahead and this is the case mostly :) – Sarfraz Feb 16 '12 at 08:34
3

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.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
2

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.

Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
  • 1
    interesting fact: `" " * 1 = 0`. i'd tell this to a math teacher someday "space multiplied once is nothing" XD – Joseph Feb 16 '12 at 08:18
  • @Joseph: It actually makes sense--`" "` is a string representation of nothing. If you multiply nothing (e.g. 0) by anything, you still get nothing. – Tikhon Jelvis Feb 16 '12 at 08:35
1

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?

Community
  • 1
  • 1
Joseph
  • 117,725
  • 30
  • 181
  • 234
1

because a string with whitespaces is converted to 0. So To compare:


if(" " !== 0) {
....

Sudhir Bastakoti
  • 99,167
  • 15
  • 158
  • 162