JavaScript

Values, types, and the equality trap

typeof, truthy and falsy, and the one comparison operator to stop reaching for.

After this lesson you can

  • Name JavaScript's primitive types and tell them from objects
  • Predict whether a value is truthy or falsy without running it
  • Explain why === is the default and when == still surprises people

JavaScript has seven primitive types: string, number, boolean, undefined, null, symbol, and bigint. Everything else — arrays, functions, dates, plain objects — is an object. There is exactly one numeric type; 1 and 1.5 are both a number.

typeof "hi";          // "string"
typeof 42;             // "number"
typeof undefined;      // "undefined"
typeof null;           // "object" — a 25-year-old bug nobody can fix now
typeof [];               // "object"
typeof (() => {});       // "function"

typeof null returning "object" is not a design choice; it is a bug from JavaScript's first implementation that shipped before anyone could fix it without breaking the web. Comparing value === null directly is the reliable way to ask.

Truthy and falsy

Every value is truthy in a boolean context except a short, fixed list: false, 0, -0, "", null, undefined, and NaN. Everything else — including "0", [], and {} — is truthy.

if ("0") console.log("truthy");   // runs: a non-empty string
if ([]) console.log("truthy");    // runs: an object, always truthy

Try it

What actually counts as falsynode-22
export function falsyOnly() {  const values = [0, 1, "", "a", null, "0", [], {}, false, true];  return values.filter((v) => !v);}
What to look for

== against ===

== compares after converting both sides to a common type. === compares without converting anything. The conversion rules for == are a genuine, memorised list of special cases:

0 == "0";           // true  — the string converts to a number
0 == "";            // true  — empty string converts to 0
0 == false;         // true  — false converts to 0
null == undefined;  // true  — the one pair == treats as equal to each other
null == 0;          // false — null converts to nothing else, not even 0
"" == "0";          // false — neither side is a number here, plain string compare

Nobody has that table memorised reliably, which is why the convention is: use === and !== everywhere, and reach for == only for the one legitimate case — value == null, which is true for both null and undefined and nothing else.

NaN is never equal to anything, including itself

NaN === NaN;         // false
Number.isNaN(NaN);   // true — the only reliable check

isNaN(x) (the global, not Number.isNaN) first converts x to a number, so isNaN("hello") is also true. Use Number.isNaN, which never converts its argument.

Try it yourself

2 visible tests · 2 hidden tests

Implement firstTruthy(values) that returns the first truthy value in the array, or null if every value is falsy. Do not convert the value — return it exactly as it was given.

  • firstTruthy([0,"",null,5,"a"])
  • firstTruthy([0,"",null,false])
Loading editor…

Sign up to check the hidden tests and save your progress. Sign up