JavaScriptnull vs undefined

null and undefined

Most languages have one "no value" placeholder. JavaScript has two: null and undefined. They mean almost the same thing in practice, but the language uses them differently and trips over its own legacy quirks (like typeof null being "object"). Knowing when each one shows up — and which operators treat them as a pair — keeps a whole category of bugs out of your code.

What each one means
  • undefined is JavaScript saying "this slot exists but no value has been put here". It is the default for declared-but-unassigned variables, missing function arguments, missing object properties and explicit return; statements.

  • null is the developer saying "this slot exists and I deliberately set it to nothing". It is rarely produced by the engine — it appears when you assign it.

JS
// Cases where JS gives you undefined
let x;                       // declared, not assigned -> undefined
function f(a) { return a; }
f();                         // undefined  — missing argument
const obj = { a: 1 };
obj.b;                       // undefined  — missing property
function noReturn() {}
noReturn();                  // undefined  — implicit return
[1, 2, 3][99];               // undefined  — out-of-range index

// Cases where you give it null
const user = { name: "Ada", manager: null };  // explicitly no manager
let selected = null;                          // "nothing selected yet"
The convention
When a function might return "no result", returning `null` is the conventional choice — it signals intent. Use `undefined` for **absence**: missing arguments, optional properties, fields you haven't filled in yet.
typeof null is "object" (a famous bug)

JS
typeof undefined;    // "undefined"
typeof null;         // "object"   ← infamous

// To check for null specifically:
value === null;

// To check for "either" null or undefined:
value == null;       // true for both null and undefined
value === null || value === undefined;
typeof null === 'object' is permanent
This is a bug from the very first version of JavaScript that can never be fixed without breaking the web. Don't rely on `typeof` to detect `null`. Compare against `null` directly.
The == null trick

== is mostly to be avoided, but there is one specific use that the entire JavaScript community has agreed to keep: x == null is shorthand for "is x either null or undefined?".

JS
null  ==  undefined;     // true   — only these two are == equal
null  === undefined;     // false
null  ==  0;             // false  — does NOT coerce to 0
undefined == "";         // false

function isNullish(v) {
  return v == null;       // succinct and idiomatic
}

isNullish(null);          // true
isNullish(undefined);     // true
isNullish(0);             // false
isNullish("");            // false
Nullish coalescing: ??

The ?? operator falls back only for null or undefined — not other falsy values. This makes it the right tool for "default value if missing":

JS
const port = process.env.PORT ?? 3000;
// undefined PORT -> 3000; "0" stays "0"

const username = input ?? "guest";

// Compare with || which falls back on any falsy value:
const wrong = 0 || 50;     // 50  — but 0 was probably intentional
const right = 0 ?? 50;     // 0   — keeps the legitimate zero
Optional chaining: ?.

Closely related: ?. short-circuits to undefined instead of throwing when you reach for a property on null or undefined. Combine it with ?? for clean default chains.

JS
const user = { profile: null };

// Old way — verbose
const city1 = user && user.profile && user.profile.address && user.profile.address.city;

// Modern way
const city2 = user?.profile?.address?.city;

// With a default
const city3 = user?.profile?.address?.city ?? "unknown";

// Also works on function calls and array indices
user.greet?.();              // call greet if it exists
arr?.[0];                    // arr[0] if arr is not null/undefined
?. is only nullish-safe
`?.` only protects against `null` and `undefined`. `{}?.foo` works fine (returns `undefined`), but `{}.foo.bar` still throws because `undefined.bar` is the error — and chaining only happens at the `?.`.
Default parameters

Function parameter defaults are triggered only by undefined (not null). This matters more often than people expect.

JS
function hello(name = "stranger") {
  return `hello, ${name}`;
}

hello();              // "hello, stranger"
hello(undefined);     // "hello, stranger"
hello(null);          // "hello, null"   — null is a real value!
hello("");            // "hello, "       — empty string is real too
hello, stranger
hello, stranger
hello, null
hello, 
Inside arrays and JSON

JS
const arr = [1, , 3];          // sparse array, hole at index 1
arr.length;                    // 3
arr[1];                        // undefined  — but it's a "hole", subtle

JSON.stringify({ a: undefined, b: null });
// '{"b":null}'   — undefined keys are dropped

JSON.stringify([undefined, null]);
// '[null,null]'  — undefined inside arrays becomes null

JSON.parse('{"a": null}').a;   // null
// JSON has no "undefined" — parsing never produces it
When to use which — quick rules
  • Use undefined by omission: leave optional parameters out, don't set properties you don't have, return nothing for "no value yet".

  • Use null by assignment: an intentional empty slot in a structured object, or "this lookup found nothing".

  • Treat them as one concept in your code: x == null or the ?? / ?. operators handle both at once.

  • Don't use typeof v === "undefined" unless you genuinely need to check whether a variable is declared. Otherwise v === undefined is clearer.

The community has converged on a simple rule: write code that doesn't care whether a missing value is null or undefined. Use ?., ?? and == null, and you'll seldom be tripped up by the difference.