Difference between equality checking inside 'if condition' vs 'console.log'

Viewed 184

I was trying out a code snippet and the results are different for an empty array check inside a console.log statement and in a conditional statement. Help/Thoughts on why this is different? Thanks in advance!

//Output: true
if([]) {
  console.log(true)
} else{
  console.log(false)
}

//Output: false
console.log([] == true)

4 Answers

My assumption is that the if/else block, in part of its "truthful" test is checking if something exists (not just if it is true or not) -- wherein the straight console print is comparing the value of the empty array against a boolean (which would be false)

let test = 'apple';
if( test ){
  console.log( 'if/else: ' + true );
}else{
  console.log( 'if/else: ' + false );
}

console.log( 'log: ' + ( test == true ) );

The two snippets are actually doing different things, hence the different results.

The first, with [] as the condition of the if statement, coerces the array to a Boolean value. (if, naturally enough, only works on Booleans, and JS will happily convert the given value if it isn't already Boolean.) This produces true - all objects in JS are "truthy", which includes all arrays.

For the second snippet, you are using the "loose equality" operator == - for which the JS specification provides a set of rules for how to convert the values into other types, eventually reaching a straightforward comparison between two values of the same type. You might want, or hope, that comparing a non-Boolean to true or false in this situation coerced the non-Boolean to Boolean - but this isn't what happens. What the specification says is that first the Boolean is coerced to number value - resulting in 1 for true (and 0 for false). So it reduces to [] == 1 - which will go through a few more conversions before resulting in a false result.

The key point is that no conversion to Boolean happens in the second case. If you think this is stupid, you're probably right. This is a bit of a gotcha, and one of the reasons many guides tell you never to use == in JS. I don't actually agree with that advice in general (and hate linters telling me to always use === in any circumstances) - but you do have to be aware of some dangers. And using == to compare a value to true or false is something to always avoid.

Luckily, if you want to test if x is truthy or falsy, you have a very short and understandable way to do it - the one you used in the first snippet here: if (x)

[edit] So my original answer was confusing as heck, and there are some incongruencies in the many answers you find on this subject all over the internet; so, let me try this again:

Part 1: Why they are Different

if([]) and if([] == true) are not the same operation. If you see the below example, you will get the same result when doing the same operation.

//Output: false
if([] == true) {
    console.log(true);
} else{
    console.log(false);
}

//Output: false
console.log([] == true);

Part 2: Why it matters AKA: the confusing bits

In JS, the following is a common expression used to see if an object/variable exists:

var foo = "Hello World";
if (foo) ...

From a design perspective, this test is not important to see if foo is equal to true or false, it is a test to see if the program can find the object or variable foo. If it finds foo, then it executes the results in the "then" condition, otherwise you get the "else" condition. So, in this case, it will convert foo to either false for does not exist, or true for does exist. So in this case the string is reduced to a boolean.

In contrast:

var foo = "Hello World";
if (foo == true) ...

Is typically trying to find out if the value of foo actually equals true. In this case, you are comparing the value of foo "Hello World" to a boolean, so in this case, "Hello World" does not equal true.

Just like foo, [] can be evaluated more than one way. An empty array is still an object; so, in the first case, it coerces to true because it wants to know if [] can be found; however, [] also equals ['']. So now picture this:

if (['bar'] == 'bar') ...

In this case, JS will not look at ['bar'] to see if it is there, but as an object containing a single value which it can convert to the string, 'bar'.

So:

if([]); // is true because it is an object test that evaluates as (1 === 1)

and

if([] == true) // is false because it is a string test that evaluates as ('' == 1) to (0 === 1)
Related