6

I have two statements like this. Why do they both evaluate to false?

console.log([] == true)
console.log(![] == true)

If [] == true is false shouldn't ![] == true result to true?

nick zoum
  • 7,216
  • 7
  • 36
  • 80
aldenn
  • 2,060
  • 2
  • 11
  • 30
  • 6
    No, if `[] == true` is `false`, then `[] != true` would be `true`. Negating one of the sides doesn't have the same semantics. Thing about it `3 == 2` is `false`, correct? So, why would `!3 == 2` be `true`? – VLAZ Oct 06 '19 at 07:25

5 Answers5

9

It's the way coercion works.

The first step of coercion is to convert any non primitive types to primitive types, then using a set of rules convert the left, right or both sides to the same type. You can find these rules here.

In your case [] == true, would pass through these 4 steps:

  1. [] == true
  2. [] == 1
  3. "" == 1
  4. 0 == 1

Whereas based on operator precedence the ! in ![] == true is executed first so the expression is converted to false == true which is obviously false.

You can try the live demo by Felix Kling to better understand how the sameness operator works.

In more words:

The value ![] is false, because [] is an Object (arrays are objects) and all objects, not including null, are truthy. So any array, even if it is empty will always be a truthy, and the opposite of a truthy is always false. The easiest way to check if a value is a truthy is by using !!.

console.log("![]: " + ![]);
console.log("!![]: " + !![]);

When you are using a loose comparison (using == instead of ===) you are asking the JavaScript engine to first convert the values into the same type and then compare them. So what happens is the values get converted according to a set of rules, once they are the same type, they get compared though the same process as a strict equality check (===). The first change that [] goes through is to get converted to a string, the string version of an empty array is an empty string "", the empty string is then converted to a number, the numeric value of an empty string is 0, since the numeric value of true is 1 and 0 != 1, the final output is false.

console.log("[] == true => `" + ([] == true) + "`");

console.log("String([]) => `" + String([]) + "`");
console.log("Number('') => `" + Number("") + "`");

console.log("Number(true) => `" + Number(true) + "`");
nick zoum
  • 7,216
  • 7
  • 36
  • 80
2

As per the Abstract Equality Comparison Algorithm - http://es5.github.io/#x11.9.3

Types of x and y are checked when x == y is to be checked.

If no rule matches, a false is returned.

  1. For [] == true , rule 7 matches, so a result of [] == ToNumber(true) is returned i.e. false is returned.
  2. Reason you're getting the same result for ![] == true, because ![] returns false, and false == true returns false .

To get opposite result for your second operation, add a precedence (i.e. wrap) to your expression with braces.

console.log(!([] == true)); // returns true
Community
  • 1
  • 1
pritam
  • 2,452
  • 1
  • 21
  • 31
1

Put ![] in the console. It's false.

So ![] == true is the same as false == true, which is false.

[] != true is true though

ba_ul
  • 2,049
  • 5
  • 22
  • 35
pixelearth
  • 13,674
  • 10
  • 62
  • 110
  • I don't think it answers the question. The question essentially is if `[]` is `false` then why is '![]` also `false`. In mathematics and logic, the negation of `false` is `true`. So this is a valid question. The answer is complicated. – ba_ul Oct 06 '19 at 08:04
  • It's not complicated. `[]` is not false. You should learn about data types, coercion, casting, equality, identity, `==` and `===`. `[] == false -> true` but `[] === false -> false`. It's not mathematics. It's programming, and there are a number of ways to conceive what something "is" depending on the equality operator, and the context. – pixelearth Oct 06 '19 at 21:42
  • Let me try again. 1. I didn't say `[]` is `false`. I was interpreting the question: if `[] == true` produces `false` then that *implies* `[]` is `false`. In JavaScript specification, an empty array is truthy. The question then is what's behind this contradiction. See Nick Zoum's and my answers above which explain the reason behind. 2. Your answer started with `![]` is `false`. This bypasses why `[] == true` is false. So it doesn't answer the question. 3. Look up discrete mathematics and propositional logic. They are the foundation of programming. – ba_ul Oct 07 '19 at 01:27
  • You mention: `[] == false -> true` but `[] === false -> false` Of course. But what does it have to do with the question? – ba_ul Oct 07 '19 at 01:28
1

None of the answers so far has addressed the main problem. [Edit: This is no longer true. See Nick Zoum's answer.]

The question essentially is this:

[] == true returns false
=> [] is not true
=> [] is false (because something not true must be false)
=> ![] should be true, since negation of false is true. Then why does ![] == true return false?


[] is actually truthy. (So ![] is actually falsy.)

Still, [] == true returns false -- the reason is coercion. It's another of Javascript's gotchas.

When an array is checked for equality explicitly against a boolean value (that is, against true or false), its elements are first converted to strings and then joined together. An empty array therefore becomes "" — therein lies the problem, because an empty string is falsy.

In brief, an empty array is truthy, but it's coerced (when being compared to a boolean value) to an empty string, which is falsy.

Note the following, which comes from https://www.nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/

Arrays are particularly weird. If you just test it for truthyness, an empty array is truthy. HOWEVER, if you compare an empty array to a boolean, it becomes falsy:

if ( [] == false ) {
     // this code runs }

if ( [] ) {
    // this code also runs }

if ([] == true) {
    // this code doesn't run }

if ( ![] ) {
  // this code also doesn't run } 

(This is because when you do a comparison, its elements are turned to Strings and joined. Since it's empty, it becomes "" which is then falsy. Yea, it's weird.)

ba_ul
  • 2,049
  • 5
  • 22
  • 35
0

Read https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

Rule in JavaScript for The Equals Operator (==)

if


type(x)            type(y)                    result

1.x and y are the same type    See Strict Equality (===) Algorithm

2.null              Undefined                 true

3.Undefined           null                    true

4. Number            String                 x == toNumber(y)

5. String            Number                  toNumber(x) == y

6. Boolean           (any)                  toNumber(x) == y

7. (any)              Boolean               x == toNumber(y)

8.String or Number    Object                x == toPrimitive(y)

9.Object            String or Number          toPrimitive(x) == y

***10.otherwise…                                 false

PRABHAT SINGH RAJPUT
  • 1,455
  • 1
  • 12
  • 31
  • Did you derive that table from the specification? It might be a good idea to add the source. – str Oct 06 '19 at 08:02
  • This answer is not very useful. You haven't explained how this table resolves the issue being discussed. – ba_ul Oct 06 '19 at 08:08