Equality of truthy and falsy values (JavaScript)

2019-01-12 13:07发布

I've encountered something which seems inconsistent on the part of the interpreter, though I know it probably makes sense and I just don't understand it. It has to do with evaluating the equality of a truthy/falsy values and Booleans.

Example 1:

if (document.getElementById('header')) {
//run code here
}

If the element with an id of 'header' is found in the document, the condition is true because the presence of an object is considered truthy.

Example 2:

if (document.getElementById('header) == true) {
// run code here
}

Presuppose the referenced element is found within the document. It was explained to me that this condition will evaluate to false because a truthy value does not equal a Boolean value of true.

This doesn't seem to make sense. The presence of the object is considered truthy due to type coercion, so therefore it should equal true even though the data types are different.

Consider the following:

(false == 0) // evaluates to true
(false === 0) // evaluates to false

This is a case where false equals 0 is true when you use the equals to operator. Because 0 is considered a falsy value, it is equal to the Boolean value of false. The values are the same and the data types are different.

To me, (document.getElementById('header') == true) and (false == 0) are the same thing. And yet, they both evaluate to something different.

Can someone please explain to me why this is the case? I've been reading different descriptions of this, but no one seems to explain it in-depth.

3条回答
何必那么认真
2楼-- · 2019-01-12 13:24

document.getElementById('header') returns a DOM object or null. So, in your second comparison (assuming it is resolving to an object), you're comparing:

if (obj == true)

A DOM object is not == to true.

To see why, you have to go to the ECMAScript rules for automatic type conversion which you can see in the ECMAScript 5 specification here: http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3.

enter image description here

The operative rules when comparing an object == boolean are all the way down to rules 9 and 10.

  1. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

  2. Return false.

Rule 9 is the first rule where Type(x) is Object and the two types are not the same, so it's the first one to check.

Since Type(y) is Boolean, it does not pass rule 9.

Thus, when it hasn't passed any rules 1-9, it evaluates to false.


When you do this comparison:

(false == 0) // evaluates to true

you're looking at rule #6 in the type conversion rules which will do:

ToNumber(false) == 0

which will resolve to:

0 == 0

which will be true.


For this one:

(false === 0)

Whenever you use ===, if the two types are different, then the result is immediately false so this evaluates to false. === requires type AND value to be the same so if the type is not the same, then it doesn't even attempt to compare the value. No type conversion is ever done with === which is one of the useful reasons to use it.


You should understand that the truthy and falsey rules apply to only a single check like this with no == or === in the comparison:

if (obj)

They do not apply when you are comparing x == y. For that, you have to refer to the type conversion rules in section 11.9.3 of the specification (linked above).

查看更多
放我归山
3楼-- · 2019-01-12 13:24

When the if() statement is executing, it's checking if there is a truthy value inside the parenthesis. The == operator is checking whether the two values are equal in nature. In JavaScript, true and false are == to 1 and 0, respectively; hence why you can type (4 + true) and get 5, or false*6 and get 0!

When you type something == true, you're really checking if something == 1. If something isn't a boolean value it's not going to be the same as 1.

Perhaps an explanation of your postulate "The presence of the object is considered truthy due to type coercion, so therefore it should equal true."

  1. If any truthy value is equal to true,
  2. then any truthy value is equal to any truthy value (by transitive property, a=b,c=b, therefore a=c),
  3. however, this would not hold true for all cases! ("blue" == "green", 5 == "six" simply because they are each non-false values. This would make the == fairly worthless!)

The conclusion does not follow, so therefore the postulate is invalid. In general, you should use === if you need to check if two things are truly the same thing.

Hopefully this clears things up!

查看更多
趁早两清
4楼-- · 2019-01-12 13:35

Presuppose the referenced element is found within the document. It was explained to me that this condition will evaluate to false because a truthy value does not equal a Boolean value of true.

You're right, it doesn't make sense because whoever explained that to you is wrong.

The presence of a DOM element will evaluate to true and if it doesn't exist, it will evaluate to false (with a double-equals vs. triple). If in the event they are using triple equals, you can simply try: !!document.getElementById('someNodeId') and it will return a boolean value.

You can always try this in the console if you want to be sure.

!!document.getElementById('notify-container');
>> true
!!document.getElementById('non-existing-node-goes-here');
>> false

Edit: I didn't read the example clearly or the example was updated. Yeah, you're using double equal. The element is truthy, but it's not "true".

查看更多
登录 后发表回答