JavaScript undefined vs null: Comparison Pitfalls You Should Know

JavaScript has two types to represent “empty values”: undefined and null. They seem similar but are completely different. Comparison operators can cause unexpected behavior, so caution is needed.


Basic Concepts

undefined

  • Declared but not assigned a value
  • Variable exists but hasn’t been initialized
  • Default return value when function returns nothing
let x;
console.log(x);           // undefined
console.log(typeof x);    // 'undefined'

function foo() {}
console.log(foo());       // undefined

null

  • Intentional absence of value
  • Explicitly assigned by developer
  • Represents “no object”
let y = null;
console.log(y);           // null
console.log(typeof y);    // 'object' (⚠️ Famous JavaScript bug)

Core: typeof Operator Pitfall

console.log(typeof undefined);  // 'undefined' ✅
console.log(typeof null);       // 'object' ❌ (bug but unfixable)

typeof null returning 'object' is a mistake from JavaScript’s first version. It can’t be fixed due to backward compatibility.

Real Problem Scenario

function processData(data) {
  if (typeof data === 'object') {
    // Assume data is an object and access properties
    console.log(data.name);  // TypeError: Cannot read property 'name' of null
  }
}

processData(null);  // Unexpected behavior!

Solution:

function processData(data) {
  if (data && typeof data === 'object') {
    console.log(data.name);  // Safe
  }
}

processData(null);  // No problem

Equality Comparison Pitfalls

== (Loose Equality)

console.log(null == undefined);   // true ⚠️
console.log(null == 0);           // false
console.log(undefined == 0);      // false
console.log(null == '');          // false
console.log(undefined == '');     // false

== performs type coercion and treats null and undefined as equal.

=== (Strict Equality)

console.log(null === undefined);  // false ✅
console.log(null === null);       // true
console.log(undefined === undefined);  // true

=== checks types too, making it safer.


Real Problem Scenarios

1. API Response Handling

// ❌ Wrong approach
function getUserName(user) {
  if (user.name != null) {
    return user.name;
  }
  return 'Unknown';
}

// Checks both null and undefined but intent is unclear
// ✅ Clear approach
function getUserName(user) {
  if (user.name !== undefined && user.name !== null) {
    return user.name;
  }
  return 'Unknown';
}

// Or simpler
function getUserName(user) {
  return user.name ?? 'Unknown';  // nullish coalescing
}

2. Optional Parameters

// ❌ Wrong approach
function greet(name) {
  if (name == undefined) {
    name = 'Guest';
  }
  return `Hello, ${name}!`;
}

greet(null);  // "Hello, null!" (unexpected result)
// ✅ Correct approach
function greet(name = 'Guest') {
  return `Hello, ${name}!`;
}

greet();          // "Hello, Guest!"
greet(undefined); // "Hello, Guest!"
greet(null);      // "Hello, null!" (explicit null is preserved)

3. Object Property Checking

const obj = { a: null, b: undefined };

// ❌ Wrong approach
if (obj.a) {
  console.log('a exists');  // Won't execute
}

if (obj.b) {
  console.log('b exists');  // Won't execute
}

// ✅ Property existence check
if ('a' in obj) {
  console.log('a exists');  // Executes
}

if (obj.hasOwnProperty('b')) {
  console.log('b exists');  // Executes
}

Empty Value Checking Patterns

1. null or undefined Check

// Method 1: Strict comparison
if (value === null || value === undefined) {
  // Handle empty value
}

// Method 2: Loose comparison (simple but intent unclear)
if (value == null) {
  // null or undefined
}

// Method 3: nullish coalescing (ES2020+)
const result = value ?? 'default';

2. “falsy” Value Check

// Includes 0, '', null, undefined, NaN, false
if (!value) {
  // Handle empty value
}

// Warning: 0 and '' also treated as empty

3. Explicit Check Function

function isEmpty(value) {
  return value === null || value === undefined;
}

function isNullOrBlank(value) {
  return value === null || value === undefined || value === '';
}

// Usage
if (isEmpty(user.name)) {
  console.log('Name is missing');
}

Recommendations

Situation Recommended Method
null/undefined check === or ??
Optional parameters Default parameters param = default
Object property existence 'key' in obj or hasOwnProperty
“falsy” value check !value (watch for 0, ‘’, NaN)
Type checking typeof with additional null check

Summary

  • typeof null returns 'object' (bug)
  • typeof undefined returns 'undefined'
  • null === undefined is false (different types)
  • null == undefined is true (loose comparison)
  • Always use ===
  • Be explicit when checking empty values

💡 TL;DR: undefined is declared but not assigned, null is intentional empty. Use === for comparisons and remember the typeof null === 'object' bug.


References