Core Concepts7 min read · Updated 2026-03-10

null vs undefined in JavaScript: What They Mean, When They Appear, and How to Handle Each

Both mean "no value" — but they mean it differently. undefined is the engine saying a value was never set. null is a developer saying this is intentionally empty. Knowing the difference prevents bugs and bad API design.

💡 Practice these concepts interactively with AI feedback

Start Practicing →

Both values represent the absence of a meaningful value. But they come from different sources, mean different things, and need to be handled differently. Treating them as interchangeable leads to subtle bugs and APIs that are hard to use correctly.

The Semantic Difference

undefined — the engine assigned this. A variable was declared but never assigned. An object property was accessed that doesn't exist. A function was called without an expected argument. A function returned without a value. In all of these cases, JavaScript itself set the value to undefined — you didn't.

null — a developer assigned this. Explicitly setting a value to null is a programmer saying "this is intentionally empty." It's a deliberate signal, not an automatic one.

let user          // undefined — declared, never assigned (engine's doing)
let count = null  // null — explicitly set to empty (developer's doing)

This is the distinction that matters for API design: if a value is undefined, something probably wasn't provided. If a value is null, a developer intentionally marked it as absent.

When undefined Appears Automatically

Uninitialized variables:

let name console.log(name)  // undefined

Missing function arguments:

function greet(name) {   console.log(name)  // undefined if called as greet() } greet()  // undefined

Missing object properties:

const user = { name: 'Alice' } console.log(user.age)    // undefined — property doesn't exist console.log(user.address?.city)  // undefined — optional chaining

Functions with no return:

function doSomething() {   // no return statement } const result = doSomething()  // undefined

Array holes:

const arr = [1, , 3]  // sparse array arr[1]  // undefined — slot exists, no value assigned

When to Use null

Use null when you are deliberately signaling absence — especially in places where undefined would be ambiguous:

// Database record: user has no profile photo yet (intentional, not missing)
const user = {
  name: 'Alice',
  avatar: null,    // deliberately empty
  bio: null,       // deliberately empty
}

// API response: field exists but has no value const response = { data: { user: null }, // user was fetched, but doesn't exist error: null, // no error occurred }

// Clearing a ref in React const ref = useRef(null) // After the component unmounts, the ref is set back to null by React

A useful pattern: resetting vs never-setting

// undefined = never provided this option
// null = explicitly clearing the option

function updateUser(id, updates) { // 'name' === undefined → don't change the name // 'name' === null → explicitly clear the name // 'name' === 'Alice' → set name to 'Alice'

if (updates.name !== undefined) { db.users.update(id, { name: updates.name }) // includes null → clears name } }

typeof: The Bug Hidden in Plain Sight

typeof undefined  // 'undefined'
typeof null       // 'object'  ← not 'null'

typeof null === 'object' is a bug from JavaScript's original 1995 implementation. In the original engine, values were stored with a type tag, and null's type tag happened to be the same as objects. The bug was never fixed because fixing it would break existing code.

This is why you should never check for null with typeof:

// ❌ Wrong — typeof null is 'object', not 'null'
if (typeof value === 'object') {
  // This runs for null too!
}

// ✓ Correct null check if (value === null) { }

// ✓ Correct null OR undefined check (covers both) if (value == null) { } // == null catches both if (value === null || value === undefined) { } // explicit

Equality Comparison

null == undefined   // true  — spec defines this explicitly
null === undefined  // false — different types (Null vs Undefined)

null == null // true null == 0 // false null == '' // false null == false // false

undefined == undefined // true undefined == 0 // false undefined == '' // false undefined == false // false

null == undefined being true with loose equality is one of the few == behaviors worth knowing. value == null is a concise way to check for either.

Nullish Coalescing vs OR — The Critical Difference

const port = config.port ?? 3000   // ?? — uses 3000 only if port is null or undefined
const port = config.port || 3000   // || — uses 3000 if port is ANY falsy value

// The difference matters when 0 is a valid value: config.port = 0

config.port ?? 3000 // 0 — correct, 0 is a valid port config.port || 3000 // 3000 — wrong, 0 is falsy so it falls through

Use ?? when null/undefined specifically means "no value provided." Use || only when you want to replace any falsy value — empty string, 0, false included.

Optional Chaining and undefined

Optional chaining (?.) returns undefined when a chain step is null or undefined:

const user = null

user?.address?.city // undefined — not an error user?.getName?.() // undefined — not an error

// Combine with ?? for defaults: user?.address?.city ?? 'Unknown' // 'Unknown'

Notice: optional chaining returns undefined, not null. Keep that in mind if you're checking what ?. produces.

Function Parameters: undefined vs null as Arguments

function process(value = 'default') {
  return value
}

process() // 'default' — no argument = undefined = triggers default process(undefined) // 'default' — explicit undefined also triggers default process(null) // null — null does NOT trigger the default parameter

Default parameters only trigger for undefined, not for null. If you want a default for both, you need ??:

function process(input) {
  const value = input ?? 'default'  // 'default' for both null and undefined
  return value
}

process(null) // 'default' process(undefined) // 'default' process('') // '' — empty string is not null/undefined

JSON Serialization Difference

const obj = {
  a: undefined,
  b: null,
  c: 1,
}

JSON.stringify(obj) // '{"b":null,"c":1}' // undefined properties are omitted entirely from JSON output // null is serialized as the JSON null literal

If you're sending data to an API, null and undefined behave completely differently. An object with undefined values will lose those fields in JSON serialization. Use null explicitly when you want the field to appear in the payload with an empty value.

The Practical Decision Rule

📚 Practice These Topics
Type coercion
4–8 questions
Objects
8–12 questions
== vs ===
3–5 questions

Put This Into Practice

Reading articles is passive. JSPrep Pro makes you actively recall, predict output, and get AI feedback.

Start Free →Browse All Questions

Related Articles

Core Concepts
map() vs forEach() in JavaScript: Which One to Use and Why It Matters
7 min read
Core Concepts
Arrow Functions vs Regular Functions in JavaScript: 6 Key Differences
9 min read
Interview Prep
Promise.all vs allSettled vs race vs any: The Complete Comparison
9 min read