Difference between null and undefined
null and undefined - both represent "no value" in JavaScript, but one appears automatically and the other only when your code puts it there.
Theory
TL;DR
undefinedis what the JavaScript engine assigns automatically to declared variables that were never given a valuenullis a value you write explicitly to say "nothing here on purpose"- Analogy:
undefinedis an empty mailbox slot (reserved, nothing delivered);nullis a note inside the slot saying "intentionally empty" - Both are falsy, so
if (!value)catches both. Use strict equality (===) to tell them apart - Rule: let
undefinedsignal uninitialized state; assignnullwhen clearing something on purpose
Quick example
let uninitialized; // undefined by default
console.log(uninitialized); // undefined
let cleared = "hello";
cleared = null; // explicit reset
console.log(cleared); // null
console.log(typeof uninitialized); // "undefined"
console.log(typeof cleared); // "object" (not "null" - historical quirk)typeof null returns "object", not "null". That is a known JavaScript bug from 1995, kept to avoid breaking existing code.
Key difference
undefined appears without you doing anything. Declare a variable without assigning it, access a missing property on an object, call a function without returning - the engine fills in undefined. null your code has to set. It communicates intent: this field exists and is intentionally empty. That distinction matters in APIs and data models, where "not there" and "deliberately absent" are two different things.
When to use
- Variable not yet assigned: leave it, the engine handles it
- Object property you want to clear: assign
null - JSON API response for an absent field: use
null(undefinedgets dropped entirely from JSON.stringify output) - Function with no
return: producesundefinedby default - Session data after logout:
req.user = nullis a deliberate clear, not a missed initialization
Comparison table
| Aspect | undefined | null |
|---|---|---|
| Origin | Automatic (engine default) | Explicit (your assignment) |
typeof | "undefined" | "object" |
Loose equality == | Equal to null | Equal to undefined |
Strict equality === | Only equal to itself | Only equal to itself |
JSON.stringify | Property dropped entirely | Serialized as "null" |
| Typical use | Missing props, uninitialized vars | Intentional empty values, API fields |
How the engine handles this
During the creation phase of an execution context, V8 assigns undefined to every declared variable before any code runs. That is why reading a var before its assignment line gives undefined instead of an error. null is stored internally as a tagged pointer to an empty slot, which is why typeof null returns "object" rather than "null".
Common mistakes
Using == when you need to know which one you have
let val = null;
if (val == null) console.log('caught'); // true, but also catches undefinednull == undefined is true. If you only want null, use val === null. If both are acceptable, val == null works, but know what you are catching.
Expecting typeof null to return "null"
if (typeof foo === 'null') {} // never executesCheck for null with strict equality: foo === null. The typeof approach does not work here.
undefined values disappearing from JSON
JSON.stringify({ a: undefined, b: null });
// Result: '{"b":null}'This trips up backend teams. An endpoint returns { field: undefined } assuming the field is present, but the client receives {}. If a field needs to appear in the payload when empty, use null.
Loose equality masking the real state
const data = { user: { profile: null } };
if (data.user.profile == undefined) {
console.log('safe'); // runs, because null == undefined
}This passes and hides the fact that profile was explicitly set to null. Use === undefined when precision matters.
Real-world usage
- React:
useState(null)as the initial state before data loads - Express:
req.user = nullafter logout signals a deliberate session clear - Redux:
state.error = nullresets error state between requests (storingundefinedinstead causes stale messages that never clear between dispatches) - Node.js
fs.readFile: theerrargument isnullon success, neverundefined - Lodash:
_.isNil(value)checksnull || undefinedwhen either is acceptable
Follow-up questions
Q: What does typeof null return and why?
A: It returns "object". In JavaScript's original C implementation, null shared the type tag for objects (0x00). The bug was never fixed to avoid breaking existing code.
Q: How do null and undefined behave in conditionals?
A: Both are falsy, so if (!value) catches both. To distinguish them, use strict equality: value === null or value === undefined.
Q: What happens to undefined in JSON?
A: JSON.stringify drops object properties with undefined values entirely. null serializes as "null". This is why APIs use null for absent data, not undefined.
Q: What is void 0 and why do some minifiers use it?
A: void 0 always evaluates to undefined. In older JavaScript without strict mode, the global undefined could be reassigned. void 0 was a safe alternative. Modern code in strict mode does not need it.
Q: How do you tell the difference between a missing key and a key set to undefined?
A: Both return undefined when accessed. But 'key' in obj returns false for a missing key and true for a key explicitly set to undefined. That is how you tell them apart at runtime.
Examples
Basic: automatic vs explicit assignment
// undefined: the engine sets it, you do nothing
let username;
console.log(username); // undefined
function greet(name) {
console.log(name);
}
greet(); // undefined - no argument passed
// null: you set it
let currentUser = null; // not logged in yet
console.log(currentUser); // nullundefined appears whenever something is missing or unassigned. null only shows up when your code puts it there.
Real scenario: Express handler and JSON output
app.get('/user/:id', (req, res) => {
const user = db.getUser(req.params.id);
if (user === undefined) {
// db.getUser found nothing - not the same as "user exists but has no role"
return res.status(404).json({ error: 'User not found' });
}
// Null out sensitive field explicitly before sending response
res.json({ ...user, passwordHash: null });
});
// GET /user/123 (found): { id: 123, name: "Alice", passwordHash: null }
// GET /user/999 (not found): 404, { error: "User not found" }db.getUser returns undefined when it finds nothing. The response sets passwordHash to null so the field still appears in the JSON output but carries no sensitive data.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.