Skip to main content

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

  • undefined is what the JavaScript engine assigns automatically to declared variables that were never given a value
  • null is a value you write explicitly to say "nothing here on purpose"
  • Analogy: undefined is an empty mailbox slot (reserved, nothing delivered); null is 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 undefined signal uninitialized state; assign null when clearing something on purpose

Quick example

javascript
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 (undefined gets dropped entirely from JSON.stringify output)
  • Function with no return: produces undefined by default
  • Session data after logout: req.user = null is a deliberate clear, not a missed initialization

Comparison table

Aspectundefinednull
OriginAutomatic (engine default)Explicit (your assignment)
typeof"undefined""object"
Loose equality ==Equal to nullEqual to undefined
Strict equality ===Only equal to itselfOnly equal to itself
JSON.stringifyProperty dropped entirelySerialized as "null"
Typical useMissing props, uninitialized varsIntentional 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

javascript
let val = null; if (val == null) console.log('caught'); // true, but also catches undefined

null == 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"

javascript
if (typeof foo === 'null') {} // never executes

Check for null with strict equality: foo === null. The typeof approach does not work here.

undefined values disappearing from JSON

javascript
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

javascript
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 = null after logout signals a deliberate session clear
  • Redux: state.error = null resets error state between requests (storing undefined instead causes stale messages that never clear between dispatches)
  • Node.js fs.readFile: the err argument is null on success, never undefined
  • Lodash: _.isNil(value) checks null || undefined when 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

javascript
// 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); // null

undefined appears whenever something is missing or unassigned. null only shows up when your code puts it there.

Real scenario: Express handler and JSON output

javascript
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 ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?