最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

if statement - Why do both if('0'==false) and if('0') evaluate to true in JavaScript? - Stack Ov

programmeradmin3浏览0评论

From what I know, the if statement in JavaScript casts the result of its condition to a Boolean, and then executes it like the following:

if(true) {
    // run this
}

if(false) {
    // do not run this
}

And that works. But If I do this:

if('0' == false) {
    // We get here, so '0' is a falsy value
}

Then I would expect this:

if('0') {
    // We don't get here, because '0' is falsy value
}

But instead, I get:

if('0') {
    // We *DO* get here, even though '0' is falsy value
}

What's happening? Apparently, if does not check if its condition is a truthy or falsy value, but does some other conversion?

From what I know, the if statement in JavaScript casts the result of its condition to a Boolean, and then executes it like the following:

if(true) {
    // run this
}

if(false) {
    // do not run this
}

And that works. But If I do this:

if('0' == false) {
    // We get here, so '0' is a falsy value
}

Then I would expect this:

if('0') {
    // We don't get here, because '0' is falsy value
}

But instead, I get:

if('0') {
    // We *DO* get here, even though '0' is falsy value
}

What's happening? Apparently, if does not check if its condition is a truthy or falsy value, but does some other conversion?

Share Improve this question edited Jan 15, 2024 at 5:33 Pang 10.1k146 gold badges86 silver badges124 bronze badges asked May 8, 2013 at 21:46 Willem MulderWillem Mulder 14k4 gold badges41 silver badges64 bronze badges 6
  • 1 '0' is not a false-y value. See the specification on why the equality works as it does (there are additional coercion rules not in [ToBoolean]). – user2246674 Commented May 8, 2013 at 21:48
  • Possibly because '0' is a String (and not a boolean itself). In order to '0' == false evaluate to true, the engine probably does some conversion before actually evaluating the expression. – acdcjunior Commented May 8, 2013 at 21:49
  • stackoverflow./questions/5659085/… – gongzhitaao Commented May 8, 2013 at 21:50
  • I think if(null) { } will also not execute in JS. Probably has something to do with the old C++ world where "anything that isn't 0 is true" – K0D4 Commented May 8, 2013 at 21:50
  • exact duplicate of Why do alert(!!"0") and alert(false == "0") both output true in JavaScript – Bergi Commented May 8, 2013 at 22:40
 |  Show 1 more ment

4 Answers 4

Reset to default 7

This is just one of those "gotchas" with the == rules which are rather plex.

The parison x == y, where x and y are values, produces true or false. Such a parison is performed as follows:

(4) If Type(x) is Number and Type(y) is String, return the result of the parison x == ToNumber(y).

(5) If Type(x) is String and Type(y) is Number, return the result of the parison ToNumber(x) == y.

(6) If Type(x) is Boolean, return the result of the parison ToNumber(x) == y.

(7) If Type(y) is Boolean, return the result of the parison x == ToNumber(y).

In this case, that means that '0' == false is first coerced to '0' == 0 (by rule #7) and then, on the second pass through, it is coerced to 0 == 0 (by rule #5) which results in true.

This particular case is somewhat tricky because of false ~> 0 instead of '0' ~> true (as what might be expected). However, '0' is itself a truth-y value and the behavior can be explained with the above rules. To have strict truthy-falsey equality in the test (which is different than a strict-equality) without implicit conversions during the equality, consider:

!!'0' == !!false

(For all values: !falsey -> true and !truthy -> false.)

This:

if('0') {
    // We *DO* get here, even though '0' is falsy value
}

checks to see if the string is null or empty, not whether it's zero or not. Any non-empty string is truthy.

When you do this:

if('0' == false) {
    // We get here, so '0' is a falsy value
}

you are asking the JS engine for an explicit type conversion to try to match the type of the two operands. That is different than just asking if one operand is truthy all by itself.

In general, you will find that you get fewer unexpected results if you nearly always use === and !== and only allow type coercion when you know exactly what is going to happen in all cases either because you fully understand the very plex coercion rules or because you know what types will be present and you understand those specific cases.

if ('0' == false):

Javascript is doing something called type coercion.

Following the rules in that link, we fall to rule 7:

If Type(y) is Boolean, return the result of the parison x == ToNumber(y)

Calling ToNumber(false) gives us a numeric 0. The result now starts to make sense, but we're still not quite done, because we still have a string and a number. The process starts again, and this time we fall to rule 5:

If Type(x) is String and Type(y) is Number, return the result of the parison ToNumber(x) == y: "2" == 2

This time, the left side '0' is converted to a number: 0. Now, at last, we can pare two Numbers, and since 0 equals 0, the result is true. However, it's important to note that this implies nothing at all about the truish/falsy nature of the '0' string, because it was coerced before it was pared.

if('0')

In this case, there is no parison; you only want to know if a single value is "truish" or "falsy". No type coercion is used, because strings can be evaluated as truish or falsy on their own merits. Using the rules at the same link as before, we find this information:

In JavaScript, and not only JavaScript, we have so called falsy values. These are respectively: 0, null, undefined, false, "", NaN. Please note the empty string is empty, 'cause differently from php as example, "0" will be considered truish

The quote is especially helpful because it specifically calls out the '0' string, but that would not be necessary. It's enough to know that an empty string is falsy, and any other string is truish, because the content of the string is not evaluated and no coercion is performed. 0 may be a falsy value, but because we evaluate a string rather than coercing to a number, and '0' has a value of some kind, it is still truish.

Javascript operator == does type conversion and is basically useless. Just avoid it.

For example:

  • [] is truty but [] == false is true
  • 1 == "1", [1] == "1", [[1]] == "1" are all true
  • [1] == [[1]] however is false

The rules are VERY weird. For example in the first case [] gets converted to "" that gets converted to a number and the value is 0. false is also converted to the number 0. So in the end they pare equal.

Note however that while the conversion from the empty string to a number gives 0, the result of parseInt("") is NaN.

PS: The real fun is when you discover that [30,20,10,3,2,1].sort() returns [1,10,2,20,3,30] (yes... numbers, yes in lexicographical order). No I'm not kidding.

发布评论

评论列表(0)

  1. 暂无评论