1

When I run the following line of code:

var x = []; console.log(!x); console.log(x == false);
> false
> true

I assumed using ! would coerce the type correctly similar to how it works in PHP, and that these two console logs would return the same output. Can someone explain to me what is going on here?

ThinkingInBits
  • 10,792
  • 8
  • 57
  • 82

3 Answers3

2

tl;dr: Converting a value to Boolean is very different from comparing a value to Boolean because JavaScript has implicit type conversion.

Can someone explain to me what is going on here?

!x is the same as doing !Boolean(x), i.e. x is explicitly converted to a Boolean.

With loose comparison, things are a little more evolved:

If the two operands are not of the same data type, JS will convert both of them to the same type. However, if any of the operands is a Boolean, that value is converted to a number, independently of the value of the other operand. That in turn means that the other operand is converted to a number as well.
So [] == false is the same as Number([]) == Number(false).

The algorithm for loose comparison can be found in the ECMAScript spec.

See also Why does {} == false evaluate to false while [] == false evaluates to true?, where I listed the conversion steps.

I assumed using ! would coerce the type correctly similar to how it works in PHP.

While there are certainly some similarities, the type conversion rules are complete independent.


Opinionated advice: This is a good example of why implicit type conversion should be avoided if possible.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Wait a second, I think your first statement about !x being the same as Boolean(x). !emptyArray returns a different output than Boolean(emptyArray) – ThinkingInBits Feb 19 '15 at 02:30
  • I have to add also, that this is a great answer. You describe it better than any of the articles I could find on google. – ThinkingInBits Feb 19 '15 at 05:26
1

Actually, I think that it does work the way you think:

var x = [];

document.writeln(!x);
document.writeln(x == false);
Ian Hazzard
  • 7,661
  • 7
  • 34
  • 60
1

Okay, so I think I found the problem:

var x=[];
alert(x==false);// true;
x=[1];
alert(x==false);// false;

Even though x is defined, it does not return true unless it has content.

Frank
  • 2,050
  • 6
  • 22
  • 40
  • Once again, I give input after the fact. Still, sometimes it's good to see the code in action, so I'll leave it up. – Frank Feb 19 '15 at 02:49