Is whitespace equals to integer 0 in Javascript? - javascript

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.

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.

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.

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) {
....

Related

Why is tab equal to false in JavaScript? [duplicate]

This question already has answers here:
Can't understand the conditional execution flow [duplicate]
(3 answers)
Closed 3 years ago.
I thought I knew about the quirks with == and all the strange type casts in JavaScript, but today I stumbled upon one thing that doesn't make any sense to me:
'\t' == false
// => true
Why is that?
Apparently, '\t' is not a falsy value, and if combined with || it works as excpected:
'\t' || 42
// => '\t'
On the other hand, a toString is also not called on false, see:
'\t' == 'false'
// => false
This led me to thinking that the tab maybe gets converted to a boolean, but:
Boolean('\t') == false
// => false
So, the question is: Why is that?
See Abstract Equality Comparison::
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
So, in your situation, x is a string, and y is a boolean. The first condition that is fulfilled here is:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
Turning the check into
'\t' == 0
Which then fulfills:
If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
And ToNumber('\t') === 0:
console.log(Number('\t'));
Turning the check into
0 == 0
which is the same as
0 === 0
or true.
Note that while a string composed of all whitespace is == false, calling Boolean on such a string will return true, because the string has a non-zero length:
console.log(
Boolean(' '),
Boolean('\t')
);
Of course, it would be best to always avoid == - use === instead, and you won't have to worry about these silly coercion rules.

If ([] == false) is true, why does ([] || true) result in []?

Was just doing some testing and I find this odd:
[] == false
Gives true, this makes sense because double equal only compares contents and not type and tries to do type-coercion. But if its comparing contents and returns true, that means [ ] is falsey (if you did [] == true you get false too), which means:
[] || false
Should give false, but it gives [ ], making it truthy? Why?
Another example:
"\n " == 0
Gives true, but "\n " || false gives "\n "? Is there an explanation for this or its just an oddity.
When I tried this in C, we get:
int x = "\n " == 0;
printf("%d\n", x);
int y = "\n " || 0;
printf("%d\n", y);
Outputs:
0
1
This makes sense, but given C's influence on Javascript, the behaviour is different.
Type conversion is not related to falsy and truthy values.
What is truthy and what is falsy is defined by the ToBoolean function defined in the specs and [] is indeed truthy.
On the other hand, [] == false returns true because of the type conversion that happens during the evaluation of the expression.
The rules of type conversion say that for x == y
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
ToNumber results in 0 for false so we're left with the evaluation of [] == 0. According to the same rules
If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
ToPrimitive results in an empty string. Now we have "" == 0. Back to our type conversion rules
If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
ToNumber results in 0 for "" so the final evaluation is 0 == 0 and that is true!
"Is false" (even with coercion) is different from "evaluates as false in boolean context." obj == false asks if the object is the boolean value false, not whether it would evaluate as such if evaluated in boolean context.
You can evaluate an object in boolean context with (!!obj).
[] == false; // true
(!![]) == false; // false
"\n " == false; // true
(!!"\n ") == false; // false
from the ECMA-262 5.1 (page 83):
If ToBoolean(lval) is true, return lval
[] || false; // []

Why does 1==1==1 return true, "1"=="1"=="1" return true, and "a"=="a"=="a" return false? [duplicate]

This question already has answers here:
How does (A == B == C) comparison work in JavaScript?
(6 answers)
Closed 8 years ago.
function a() { return (1 == 1 == 1); }
function b() { return ("1" == "1" == "1"); }
function c() { return ("a" == "a" == "a"); }
I tested the above code in Chrome's console and for some reason, a() returns true, b() returns true, and c() returns false.
Why is this so?
Because you are comparing the (boolean) result of the first equality with the (non-boolean) third value.
In code, 1 == 1 == 1 is equivalent to (1 == 1) == 1 is equivalent to true == 1.
This means the three methods can be written more simply as:
function a() { return (true == 1); }
function b() { return (true == "1"); }
function c() { return (true == "a"); }
These comparisons work according to these rules (emphasis mine):
If the two operands are not of the same type, JavaScript converts the
operands, then applies strict comparison. If either operand is a
number or a boolean, the operands are converted to numbers if
possible; else if either operand is a string, the string operand is
converted to a number if possible. If both operands are objects, then
JavaScript compares internal references which are equal when operands
refer to the same object in memory.
So what happens in c is that "a" is converted to a number (giving NaN) and the result is strictly compared to true converted to a number (giving 1).
Since 1 === NaN is false, the third function returns false. It's very easy to see why the first two functions will return true.
Because 1 == true
But "a" != true
So basically what happens is that
1 == 1, "1" == "1" and "a" == "a" are all evaluated to be true and then compared to the next value.
The string "1" is converted to a number (1) prior to being compared to true and is thus also considered to be equal to true.
Now, the "WHY?!?!" question is explained by the fact that Javascript has its roots in the C-family of languages. In which any number, other than 0 is considered to be a valid true boolean. :-/
Because 1 and "1" are both converted to true, as numbers. This is not the case with "a". Therefore:
("1" == "1" == "1")
evaluates to
(("1" == "1") == "1")
which evaluates to
(true == "1")
Similarly,
("1" == 1 == "1")
is also true, or any combination thereof. In fact, any non-zero number when converted to a boolean is true.
Whereas, "a" does not evaluate to true.
It's because JavaScript is a weakly typed language. This means that it is not expressive enough to talk about types, and in fact implicitly coerces values to belong in types to which they have no semantic relation. So, (1 == 1) == 1 evaluates to true because (1 == 1) correctly evaluates to true, so that JavaScript evaluates (true) = 1. In particular, it is turning 1 to a boolean (or true to a number -- I forget which, but the result is effectively the same).
The point is that JavaScript is turning one type of value into another type of value behind your back.
Your question shows why this is a problem: ('a' == 'a') == 'a' is false, because ('a' == 'a') is true, and JavaScript ends up comparing (true) == 'a'. Since there is just no sensible way to turn a Boolean into a letter (or a letter into a boolean), that statement is false. Of course, that breaks referential transparency for (==).
It's true that (1 == 1) == 1. Then it will be true == 1, but not in a == a == a.
Boolean handled as bits, each bit stands for true or false ( 1 for true, 0 for false )
so that 1 stands for true, and 0 stand for false
and 1 == 1 == 1 will be like (1 == 1) == 1, true == 1, true
while 'a' == 'a' == 'a' will be ('a' == 'a') == 'a', true == 'a', false
BONUS: 0 == 1 == 0, 1 == 0 == 0 and 0 == 0 == 1 returns true

When is (true == x) === !!x false?

JavaScript has different equality comparison operators
Equal ==
Strict equal ===
It also has a logical NOT ! and I've tended to think of using a double logical NOT, !!x, as basically the same as true == x.
However I know this is not always the case, e.g. x = [] because [] is truthy for ! but falsy for ==.
So, for which xs would (true == x) === !!x give false? Alternatively, what is falsy by == but not !! (or vice versa)?
"So, for which xs would (true == x) === !!x give false?"
Any x where its Boolean conversion is not the same as its conversion by the Abstract Equality Comparison Algorithm.
An example is a string with only whitespace:
var x = " ";
Its Boolean conversion is true (as is the case with any non-empty string), but its == comparison is false because a string with only white space will be converted to the number 0, and the true value will be converted to the number 1, and those values are not equal.
x == true; // false
!!x; // true
or to show the ultimate values the == is comparing:
Number(true) == Number(x);
// 1 == 0
1 == 0; // false
and to show the result of !!x, it would be equivalent to this:
Boolean(x); // true
So your original expression could crudely be seen as the following:
var x = " ";
(Number(true) == Number(x)) === Boolean(x);
// ( 1 == 0 ) === true
// ( false ) === true
false === true; // false
I say "crudely" because this certainly doesn't capture all the detail of the algorithm linked above, and won't be the same for all values provided to the operands.
To understand how == treats its operands, you really need to study the algorithm a bit.
Loose equality has nothing to do with truthiness.
The rules for loose equality basically involve comparing the results of the .valueOf() function for each object.
For more details, see the spec.

Difference between Boolan(!x) and Boolean(x==0)?

Code-snippet 1:
if ( !x ) { /* do stuff */ }
Code-snippet 2:
if ( x == 0 ) { /* do stuff */ }
For what values of x do these two code-snippets differ?
I am asking because, although I read the chapter on == in the spec, I still find it hard to deal with situations like the above (where it is combined with ToBoolean coercion).
btw, I want to know this just for the sake of knowing it (I want to understand the language), so don't bother telling me about === or asking me what x is.
Update: I corrected the fist snippet. I meant !x.
[] == 0 is true; ![] is false
null == 0 is false; !null is true
NaN == 0 is false; !NaN is true
undefined == 0 is false; !undefined is true
!x will check whether x is "falsy".
x == 0 will check whether x is "equivalent to" 0.
Both of these terms are defined by the Javascript spec.
The following will give you true for the first and false for the second snippet:
NaN
null
undefined
And these will give you false for the first and true for the second snippet:
[]
"0" and any other string that converts to 0 using Number(x) such as "00", "000", "+0", and "-0" (which I will now call "noughty strings")
an array containing a single element that is 0, null, undefined or an empty or noughty string.
For everything else you'll get the same result for both snippets, although there may be one or two more cases I haven't thought of.
Here's an interesting one with regard to a non-empty String that has only space characters:
!!" "; // true
" " == true; // false
This is because when you do a == comparison, and one of the values being compared is a number or a boolean, an attempt is made to convert the other value to a number.
The reason you get the different result is that a string with only space characters converts to the number 0 (or falsey), while a string with only spaces converted to boolean via !! is seen as a non-empty string, and therefore true.
So:
var x = " ";
alert( !x ); // false
alert( x == 0 ); // true
EDIT:
Probably the key thing to remember is that when comparing a number or boolean to a non number type, == uses toNumber conversion if possible, while ! uses toBoolean conversion. They're not always the same.
It is easy to see the result of the toBoolean conversion using !!. As in:
alert( !![] ); // true
But you can't really see the result of the toNumber conversion when using ==.
You can, however, use the unary + to see the result of a toNumber conversion. As in:
alert( +[] ); // 0
I'm pretty sure that what happens in the case of an Array, is that it first gets a toString call. Therefore:
// ---------------------toString result-------toNumber result (from string)
alert( +[] ); // "" 0
alert( +[""] ); // "" 0
alert( +[" "] ); // " " 0
alert( +[0] ); // "0" 0
alert( +["0"] ); // "0" 0
alert( +["3"] ); // "3" 3
alert( +[3,4] ); // "3,4" NaN
Short answer: the two are almost always the same but not 100% the same.
An example would be (!'0') which is false whereas ('0' == 0) is true
Details:
From: http://www.joeyjavas.com/2007/08/04/javascript-true-false-checking-for-boolean-values/
Checking if a value is true or false is simple in JavaScript. All values evaluate to true, except for:
0
-0
null
undefined
NaN
empty string
false
Therefore, (!x) will be true for all of the above values of x and only those.
As for (x == 0), it will be true for any value of x which - when converted according to "==" conversion rules - is converted to 0 when compared to a number (for example, Boolean false value). Other examples that compare true to ==0 are objects which generate 0 from their valueOf() methods, or a string '0', or an empty Array ([])
The first test will succeed when x is non-zero, or evaluates to an object (as opposed to null or undefined), or is a non-empty string. So if x is 0 then the condition fails, but if it is "0" then it succeeds.
The second test will succeed when x is convertible to 0. This means it must not be null, undefined, or an object to pass this test. And it may be "0" or "".
In other words, these conditionals are not opposites. The value "0" will pass both tests, for example.
Code Snippet 1 will execute if x is "falsy" value. In Javascript, this means 0, -0, null, undefined, NaN, "", or false. Code Snippet 2, however, will only execute if x is zero. Unlike the first condition, this does not include other "falsy" values.
The difference between the two is that
if ( x ) { ... }
Tests whether x is "truthy"
Whereas
if ( x == 0 ) { ... }
Does type coercion between x and 0.
I presume you mean something like
if (x == 0) vs if (!x)
The main difference is type coercion of x to a number vs checking if x is falsy.
Clearly NaN itself will never equal 0 since its not a number. undefined will also coerce to NaN so that is not caught by == 0 I can't give a good explanation why null is not caught by 0 since Number(null) == 0
After some lookups, have to change my awnser.
There's no simple logic, implicit equality operations follows an algorithm.
http://interglacial.com/javascript_spec/a-11.html#a-11.9.3
I can't sum it up better then what the algoritm describes, it would just get more confusing.
So it's (!x) is equivalent to (typeof x === false) aka (not true)
And (x == 0) gets compared by algorithm.

Categories