The following shows that
>>> "0" == false true >>> false == "0" true
So why does the following print
>>> if ("0") console.log("ha") ha
The reason is because when you explicitly do
"0" == false, both sides are being converted to numbers, and then the comparison is performed.
When you do:
if ("0") console.log("ha"), the string value is being tested. Any non-empty string is
true, while an empty string is
(From Comparison Operators in Mozilla Developer Network)
Tables displaying the issue:
Moral of the story use ===
It's according to spec.
12.5 The if Statement ..... 2. If ToBoolean(GetValue(exprRef)) is true, then a. Return the result of evaluating the first Statement. 3. Else, ....
ToBoolean, according to the spec, is
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
And that table says this about strings:
The result is false if the argument is the empty String (its length is zero); otherwise the result is true
Now, to explain why
"0" == false you should read the equality operator, which states it gets its value from the abstract operation
GetValue(lref) matches the same for the right-side.
Which describes this relevant part as:
if IsPropertyReference(V), then a. If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below. b. Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument
Or in other words, a string has a primitive base, which calls back the internal get method and ends up looking false.
If you want to evaluate things using the GetValue operation use
==, if you want to evaluate using the
=== (also known as the "strict" equality operator)
It's PHP where the string
The trick is that
== against a boolean doesn't evaluate in a boolean context, it converts to number, and in the case of strings that's done by parsing as decimal. So you get Number
0 instead of the truthiness boolean
This is a really poor bit of language design and it's one of the reasons we try not to use the unfortunate
== operator. Use
// I usually do this: x = "0" ; if (!!+x) console.log('I am true'); else console.log('I am false'); // Essentially converting string to integer and then boolean.
"0"is a string, and since it's not empty, it's evaluated to true.
"0" === false [...] false
- @Linsey: The whole "falsy" and "truthy" thing was only ever meant to explain how values are converted to booleans. When you compare two values with
==, they never get converted to booleans, so it doesn't apply. (The rules for the conversion seem to favour converting to numbers.)
- It makes much more sense with another order of values gist.github.com/kirilloid/8165660
- From now on, if someone says that he never uses strict comparison operators, I will face him with these tables and make him cry. Still not sure if I grasp the concept of
NaNthough. I mean,
typeof NaN // numberbut
NaN === NaN // false, hmm...
- @JustusRomijn there are multiple values to represent
NaN, so when you are comparing 2 NaNs, they are of different values (I guess). Read the first quote here.
- These tables have a mistake. Neither
===operator for the
values do not evaluate to true. I mean
 == and
 === also false.
"a string has a primitive base, which calls back the internal get method and ends up looking false"Is this true for all strings ?
Section 8.12.3: [[Get]] (P)describes how it works. It's true only for cases that string are 0, as it does a bunch of other internal calls eventually resulting in
- Where can I find the spec?
- correct, not about how to "make it work" but the question is more like, "why it behaved that way?"
- I didn't know someone ported the spec to a site... that's awesome! No more PDFs for me.