JavaScript Interview Prep
Type System & Coercion

NaN, null, undefined

The Three Empty Parking Spaces

LinkedIn Hook

typeof null is "object". It has been since 1995 — and it will stay that way forever.

NaN !== NaN. The only value in JavaScript that isn't equal to itself.

isNaN("hello") returns true. But Number.isNaN("hello") returns false. One of them has a bug. Can you guess which?

These three values — NaN, null, undefined — look similar but behave completely differently. Mixing them up is how bugs silently survive to production.

In this lesson you'll learn when each one appears, why typeof null is a 30-year-old bug, the critical difference between isNaN() and Number.isNaN(), and the one-liner that reliably checks for both null and undefined.

If an interviewer asks "what's the difference between null and undefined?" — this lesson gives you the answer they're really testing for.

Read the full lesson -> [link]

#JavaScript #InterviewPrep #NaN #NullVsUndefined #Frontend #CodingInterview #WebDevelopment


NaN, null, undefined thumbnail


What You'll Learn

  • Exactly when undefined, null, and NaN each appear — and what they really mean
  • Why typeof null is "object" (and why it will never be fixed)
  • How to reliably check for NaN and for "null or undefined" in one expression

Three Empty Parking Spaces

Think of a variable as a parking space. undefined means the space was reserved but no car has parked yet. null means someone deliberately put a "space intentionally empty" sign. NaN means someone tried to park a banana — the system expected a car (number) but got something nonsensical.

When Each Appears

// undefined -- "declared but not assigned"
let x;
console.log(x); // undefined

function greet(name) {
  console.log(name); // undefined if no argument passed
}
greet();

const obj = { a: 1 };
console.log(obj.b); // undefined -- property doesn't exist

function noReturn() { /* no return statement */ }
console.log(noReturn()); // undefined

// null -- "intentionally set to nothing"
const user = null; // we explicitly set this

// Common API pattern: "no result found"
document.getElementById("nonexistent"); // null

// Clearing a reference
let cache = { data: [1, 2, 3] };
cache = null; // intentionally cleared

// NaN -- "failed numeric operation"
const result = parseInt("hello"); // NaN
const math = 0 / 0;               // NaN
const bad = undefined + 1;        // NaN
const oops = Math.sqrt(-1);       // NaN

typeof Results — The Historical Bug

typeof undefined;  // "undefined" -- correct
typeof null;       // "object"    -- BUG! (since 1995, never fixed)
typeof NaN;        // "number"    -- technically correct (NaN is a numeric type)

// Why typeof null === "object":
// In the original JS engine, values were stored as a type tag + value.
// Objects had type tag 0. null was the NULL pointer (0x00).
// So null's type tag was also 0, making typeof think it's an object.
// It's been a known bug since 1995 but can't be fixed without
// breaking millions of websites.

Equality Comparisons Between Them

// null and undefined are loosely equal to each other
null == undefined;   // true (special spec rule)
null === undefined;  // false (different types)

// null and undefined are NOT equal to anything else with ==
null == 0;           // false
null == "";          // false
null == false;       // false
undefined == 0;      // false
undefined == "";     // false
undefined == false;  // false

// NaN is not equal to ANYTHING -- not even itself
NaN == NaN;          // false
NaN === NaN;         // false
NaN != NaN;          // true -- the only value where this is true!

Number.isNaN vs Global isNaN

// Global isNaN() -- COERCES the argument to number first, then checks
isNaN(NaN);       // true -- correct
isNaN("hello");   // true -- MISLEADING! "hello" isn't NaN, but
                  //         Number("hello") is NaN, so it returns true
isNaN(undefined); // true -- Number(undefined) is NaN
isNaN("123");     // false -- Number("123") is 123, not NaN
isNaN("");        // false -- Number("") is 0, not NaN

// Number.isNaN() -- NO coercion, checks if the value IS ACTUALLY NaN
Number.isNaN(NaN);       // true -- correct
Number.isNaN("hello");   // false -- "hello" is a string, not NaN
Number.isNaN(undefined); // false -- undefined is not NaN
Number.isNaN(123);       // false -- 123 is not NaN

// ALWAYS use Number.isNaN() -- the global isNaN is essentially broken

Checking for null and undefined

// Check for null specifically
value === null;

// Check for undefined specifically
value === undefined;
typeof value === "undefined"; // safe even if variable is undeclared

// Check for either null or undefined
value == null;  // true for both null AND undefined (the one good use of ==)
value == null;  // equivalent to: value === null || value === undefined

// Modern: nullish coalescing and optional chaining
const name = user?.profile?.name ?? "Unknown";

NaN, null, undefined visual 1


Common Mistakes

  • Using the global isNaN(x) for input validation — it coerces first, so isNaN("hello") is true. Use Number.isNaN(x) instead.
  • Checking value == null || value == undefined — that's redundant. value == null already matches both (and only both).
  • Treating undefined as something you should manually assign. Let JavaScript produce undefined; use null when you want to say "intentionally empty."

Interview Questions

Q: What is the difference between null and undefined?

undefined means a variable has been declared but not assigned a value -- it's the default state. null is an explicit assignment meaning "intentionally no value." undefined is typically assigned by JavaScript, while null is assigned by the developer.

Q: Why does typeof null return "object"?

It's a historical bug from JavaScript's first implementation in 1995. Values were stored with type tags, and the tag for objects was 0. Since null was represented as the NULL pointer (0x00), its type tag was also 0, so typeof incorrectly identifies it as "object". This was never fixed to maintain backward compatibility.

Q: What is the difference between isNaN() and Number.isNaN()?

The global isNaN() coerces its argument to a number first, so isNaN("hello") returns true (because Number("hello") is NaN). Number.isNaN() does NOT coerce -- it returns true only if the value is actually NaN. Always prefer Number.isNaN().

Q: How can you check if a value is NaN?

Use Number.isNaN(value). Alternatively, NaN is the only value where value !== value is true, so that self-inequality check also works.

Q: Why is NaN !== NaN?

The IEEE 754 floating-point standard defines NaN as "not equal to anything, including itself." JavaScript inherits that behavior, which is why NaN === NaN and NaN == NaN both return false. This self-inequality is actually a useful signature: x !== x is true only when x is NaN.

Q: How do you check if a value is null or undefined in one comparison?

Use value == null. Because of the spec rule that null == undefined, this single check returns true for both null and undefined and is equivalent to value === null || value === undefined.


Quick Reference — Cheat Sheet

NaN / null / undefined -- QUICK MAP

Meaning:
  undefined  -> declared, not assigned (JS assigns it)
  null       -> intentionally empty (YOU assign it)
  NaN        -> failed numeric operation (type: number)

typeof results:
  typeof undefined  -> "undefined"
  typeof null       -> "object"   (1995 bug, never fixed)
  typeof NaN        -> "number"

Equality:
  null == undefined   -> true  (only each other)
  null === undefined  -> false
  NaN == NaN          -> false
  NaN === NaN         -> false
  x !== x             -> true only when x is NaN

Checking:
  Number.isNaN(x)    -- the correct NaN check (no coercion)
  isNaN(x)           -- legacy, coerces: avoid
  value == null      -- matches null OR undefined in one shot
  typeof v === "undefined"  -- safe even if v is not declared
  user?.x ?? "fallback"     -- modern null/undefined-safe access

Previous: Truthy / Falsy -> The Nightclub Bouncer Next: Symbol & BigInt -> The Two Newest Primitives


This is Lesson 8.5 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.

On this page