Falsy Javascript values

Have you ever felt unconfident writing "if" conditions? Had you ever written such pieces of code like this:

if (typeof x == "undefined") {
  // do some stuff
}

If so, you are welcome to the journey into the weird world of falsy Javascript values!

What falsy values are

In Javascript, we are working usually with four primitive types: numbers, strings, booleans, and objects. For each type, Javascript has special values which help us to express the ideas of the zero element or the absence of a value:

TypeFalsy value
number0 and NaN
string""
booleanfalse
objectnull

This table would be not full without our favorite value undefined. We all love the message "undefined is not a function", don't we?

undefined is a very special value. It has its own type:

console.log(typeof undefined) // will output "undefined"

Uninitialized variables and an object's nonexistent properties will have the value undefined by default.

Falsy values and if

Falsy values are designed to make the if-else clause run the else part. The code below will output "No" six times:

var xs = [
  false,
  null,
  undefined,
  NaN,
  0,
  ""
]

xs.forEach(x => {
  if (x) {
    console.log('Yes')
  } else {
    console.log('No')
  }
})

So, with if you can be sure that falsy value will work as you expect. Do you feel now a bit more confident? Great. Because the logic ends here. Now let's talk about really weird things.

Falsy ways of usage falsy values

In all previous snippets, I deliberately omitted any comparison operators like ==. I will explain why. Let me first modify the previous snippet for it returns "Yes" at the else part:

var xs = [
  false,
  null,
  undefined,
  NaN,
  0,
  ""
]

xs.forEach(x => {
  if (!x) {
    console.log('No')
  } else {
    console.log('Yes')
  }
})

As you may think, the result should not change. And it is really the same. "No" will be printed 6 times. But let's modify it again a little bit:

var xs = [
  false,
  null,
  undefined,
  NaN,
  0,
  ""
]

xs.forEach(x => {
  if (x == false) {
    console.log('No')
  } else {
    console.log('Yes')
  }
})

This code will output: "No, Yes, Yes, Yes, No, No". But why?

The reason is not so easy to explain... There is a difference between !x and x == false. The first operator performs coercion while the second one compares two values.

You may say that this does not have any sense, and, probably, I will agree with you. But we are using Javascript and thus just need to know all these caveats.

What about [] and {}?

It is interesting that MDN does not mention any of these values in their article about falsy values. Here are some useful facts about them.

{} by no means behaves as falsy value. But [] may behave as falsy value:

console.log([] == false ? "Yes" : "No") // will output "Yes"

On the other hand, within the if statement [] is treated as a truthy value, i.e. it makes the statement execute if part but not the else part.

if ([]) {
  console.log("Yes")
} else {
  console.log("No")
}

// The code will output "Yes"

And, of course [] is not equal to another [] because they are two different objects.

And how to live with all this?

Yes, it is not easy to remember all these details. But these tips will help you to avoid mistakes in your code:

  • null, undefined, and NaN are not equal to false. But you may use them without a comparison operator within if statements.
  • NaN is not equal even to itself. For checking that something is equal to NaN use ES6 function Number.isNan().
  • Remember that [] behaves as a falsy value in comparisons. But not within the if statement.
  • {} is not a falsy value.

Cheatsheet table

The exhaustive cheatsheet of falsy Javascript values' relationships and behavior can be represented as a table:

Falsy values relationships

The last row assumes that you put the value in the if statement into its parenthesis as is, without any other values or operators.