undefined and null

JavaScript has two primitive types that each hold exactly one value: the type Undefined holds undefined, and the type Null holds null. The language itself produces undefined whenever something has no value yet: a declared but unassigned variable, a missing object property or array element, a parameter the caller left out, and the result of a function without return. null is never produced by the engine on its own (apart from APIs such as document.getElementById() or Object.getPrototypeOf(Object.prototype)); you write it to say "this is intentionally empty". A useful convention: read undefined, assign null.

How undefined and null differ
Behavior undefined null
typeof "undefined" "object" (a historical bug)
Number(value) NaN 0
JSON.stringify({ k: value }) property omitted {"k":null}
Triggers a default parameter yes no
value == null true true
undefined, null, equality and defaultsJavaScriptLive
let a;                                  // declared, never assigned
const user = { name: "Ann", phone: null }; // null: "deliberately empty"
console.log(a, user.email, typeof a, typeof null);
console.log(null == undefined, null === undefined, null == 0, null + 1, undefined + 1);
const greet = (who = "guest") => `Hi ${who}`;
console.log(greet(undefined), greet(null));
console.log(user.phone ?? "no phone", user.address?.city);

Loose equality treats null and undefined as equal to each other and to nothing else, so value == null is the one accepted use of ==: it tests for both in a single comparison. Prefer the nullish operators ??, ??= and ?. (see ?., ?? and **) over || when 0, "" or false are valid values. typeof undeclaredName safely returns "undefined", but a let, const or class binding used before its declaration throws a ReferenceError even inside typeof: the time between entering the scope and reaching the declaration is the temporal dead zone (Scoping and Hoisting), whereas var is hoisted as undefined.

undefined is a read-only global property, not a keyword, so old code wrote void 0 to be safe from shadowing. In modern code, simply never name a variable undefined.