0

Hello fellow JS junkies. Can someone please explain to me the difference between the following ways of evaluating truthiness of variables?

var q1Var1 = "hello",
        q1Var2 = 0,
        q1Var3 = true,
        q1Var4 = "false",
        q1Var5 = -1,
        q1Var6 = undefined,
        q1Var7 = null,
        q1Var8;

// What is the difference between this block of code:

console.log( !q1Var1 );
console.log( !q1Var2 );
console.log( !q1Var3 );
console.log( !q1Var4 );
console.log( !q1Var5 );
console.log( !q1Var6 );
console.log( !q1Var7 );
console.log( !q1Var8 );

// and this block?

if( q1Var1 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var2 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var3 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var4 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var5 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var6 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var7 === true ){ console.log( "true" ) } else { console.log( "false" ) };
if( q1Var8 === true ){ console.log( "true" ) } else { console.log( "false" ) };

I was expecting to find that the second block would just be an inverse of the first (in other words, the values would just switch), however, it looks like only the variable set to nonstring "true" actually returns true. Why is this? What is the fundamental difference between the two evaluations:

!q1Var1

vs.

true === q1Var1
outis
  • 75,655
  • 22
  • 151
  • 221
gogogadgetinternet
  • 5,719
  • 4
  • 24
  • 28
  • 1
    see http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use - doing `!q1Var1` is the same thing as testing `q1Var1 == false` then just look the difference between == and === – dievardump Oct 29 '12 at 18:01
  • see http://stackoverflow.com/questions/5515310/is-there-a-standard-function-to-check-for-null-undefined-or-blank-variables-in/5515349#5515349 – jAndy Oct 29 '12 at 18:02
  • dievardump - Thanks this is more along the lins of what I was looking for... testing that out now. – gogogadgetinternet Oct 29 '12 at 18:13
  • @dievardump - I see, I misread that, I am going to remove my comment. – Travis J Oct 29 '12 at 20:34
  • 1
    Ok, correction : `!q1Var1` does not give the same result as `q1Var1 == false` for undefined values – dievardump Oct 29 '12 at 20:57

4 Answers4

7

This illustrates the notion of "falsy" values in JavaScript. For instance, undefined becomes the same as false in a boolean context (such as an if condition). However, undefined === false is not true. The following are all "falsy" values:

  • false
  • undefined
  • the empty string
  • the number 0
  • null
  • NaN

The === operator means "strictly equal" (see here, for instance); it suppresses automatic type conversions.

Type conversion rules for the == operator (from the second link above) are:

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

Strict comparison rules are:

  • Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions
  • Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything, including NaN. Positive and negative zeros are equal to one another
  • Two Boolean operands are strictly equal if both are true or both are false
  • Two objects are never equal for either strictly or abstract comparisons
  • An expression comparing Objects is only true if the operands reference the same Object
  • Null and Undefined Types are == (but not ===)

Note in particular that !var is not the same as var == false (and certainly not the same as var === false if var is not a boolean value to begin with). Non-empty strings are "truthy" (!"..." is always false for any non-empty "..."), but non-empty strings that evaluate to 0 when converted to numbers (like "0") are == false.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 3
    Needs more substance, explain the `===` non-casting compare perhaps. – TheZ Oct 29 '12 at 18:00
  • @TheZ - I was getting there. :) – Ted Hopp Oct 29 '12 at 18:03
  • +1 Indeed! A little spacing out for readability and you've got yourself a fine answer. – TheZ Oct 29 '12 at 18:05
  • Sorry - I updated the first block with what I thought I had pasted! Thank you for your clearing that up. – gogogadgetinternet Oct 29 '12 at 18:05
  • Since you were the first I'll ask: What if I were to change all of the === to just ==? What is the difference then? I am still not receiving expected results... – gogogadgetinternet Oct 29 '12 at 18:11
  • @user446936 - The differences are not due just to the difference between `==` and `===`. Take the first case: `"hello"` is neither `true` not `false`, but `!"hello"` is `false` because any non-empty string is a "truthy" value. Thus `"false"` is printed in both cases. – Ted Hopp Oct 29 '12 at 18:21
  • @user446936 - I added a little more explanation to my answer – Ted Hopp Oct 29 '12 at 18:41
0

The === operator can be a little confusing and is sometimes overused. When using the === operator, it is important to keep in mind that it compares type and value. Thus, when a statement like this is used:

if( q1Var1 === true ) 

It requires that q1Var1 be of the same type and value of true. If the situation is setup like this:

q1Var1 = 1; 
if (q1Var1 === true) { console.log(true); } else { console.log(false); }//false

Then the console will log false because 1 is not the same type and value as true.

However, using the == operator, the console will log true because 1 is the same value as true.

This can be observed with:

if (1 == true) { console.log(true); } else { console.log(false); }//true
if (1 && true) { console.log(true); } else { console.log(false); }//true

On the other end,

if( !q1Var1 ); 

tests if q1Var1 is 0. Notably, because false also equates to 0 in value (but still not in type),

if (0 && false) { console.log(true); } else { console.log(false); }//true (same value)
if (0 == false) { console.log(true); } else { console.log(false); }//true (same value)
if (0 === false) { console.log(true); } else { console.log(false); }//false (same value, different type)

this test can be true with numbers as well as the boolean values because there is no test of type.

if (!0) { console.log(true); } else { console.log(false); }//true
if (!false) { console.log(true); } else { console.log(false); }//true
Travis J
  • 81,153
  • 41
  • 202
  • 273
0

When we have 2 different operands of an operation an interpretation (type transformation) of the first value sholuld be made to return the result in the type of the second operand and that is called type cast. In conditional equations the result shoold be boolean type so the result is always casted to boolean, so returning to your question, all this examples are cast of different types to boolean. In javascript casting is made automatically, but in some languages especially when using strict syntax you schould specify the casting by yourself, otherwise your log will be full of errors.

Reflective
  • 3,854
  • 1
  • 13
  • 25
0

As I understand it, the second set of tests (q1Var1 === true) are looking for absolute equality. It doesn't default to truthiness because it's looking for a perfect match.

Whereas the first set, and I'm a little fuzzy on this bit, I think is testing for an object because the test doesn't have context... at least, I think that's what's happening... o.o

monners
  • 5,174
  • 2
  • 28
  • 47