JavaScript by Example

Booleans

The true/false type - including the eight falsy values, truthy coercion, and why == is a trap you should never step in.

A boolean is one of two values: true or false. Comparisons (===, <, >=) produce booleans. Logical operators help you build conditions, but && and || return one of their operands instead of always returning true or false, so they show up everywhere even when you don't declare booleans explicitly.

Boolean literals are true and false. typeof confirms the type. Comparison expressions evaluate to a boolean you can store or pass like any other value.

const isLoggedIn = true;
const hasErrors = false;
 
console.log(typeof isLoggedIn); // "boolean"
 
const age = 20;
const isAdult = age >= 18;
console.log(isAdult); // true
 
const name = "Alice";
const isEmpty = name === "";
console.log(isEmpty); // false

&& and || short-circuit. They do not always return a boolean, they return the value that decides the expression. That is why they are common for defaults and guard clauses.

console.log(true && "ready"); // "ready"
console.log(false && "ready"); // false
 
console.log("" || "fallback"); // "fallback"
console.log("primary" || "fallback"); // "primary"
 
console.log(Boolean("primary" || "fallback")); // true

JavaScript has exactly eight falsy values: false, 0, -0, 0n, "", null, undefined, and NaN. Everything else is truthy. Boolean(x) converts any value to its boolean equivalent, which is what an if statement does internally.

// All eight falsy values
console.log(Boolean(false));     // false
console.log(Boolean(0));         // false
console.log(Boolean(-0));        // false
console.log(Boolean(0n));        // false
console.log(Boolean(""));        // false
console.log(Boolean(null));      // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN));       // false
 
// Everything else is truthy
console.log(Boolean("0"));   // true  - non-empty string
console.log(Boolean([]));    // true  - empty array
console.log(Boolean({}));    // true  - empty object
console.log(Boolean(-1));    // true  - non-zero number

== (loose equality) coerces both sides to the same type before comparing, producing results that surprise almost everyone. === (strict equality) never coerces: different types are never equal. Prefer === everywhere.

// Loose equality surprises
console.log(0 == false);         // true  (0 coerces to false)
console.log("" == false);        // true  ("" coerces to 0, false to 0)
console.log(null == undefined);  // true  (special case in the spec)
console.log("1" == 1);           // true  (string coerced to number)
 
// Strict equality - type must match
console.log(0 === false);        // false
console.log("" === false);       // false
console.log(null === undefined); // false
console.log("1" === 1);          // false

In production

Always use === and !==. The loose equality coercion table (0 == false, "" == false, null == undefined) is not intuitive and produces bugs that are hard to spot in code review. Most ESLint configs include the eqeqeq rule that bans == outright. Teams that skip it eventually ship a bug where an empty string or zero is treated as falsy in a place that should only treat null/undefined that way.

Enjoyed this? Get more software craft delivered to your inbox.