Check if object property is undefined in JavaScript

There is a common error in JavaScript that occurs when you try to access a property or a method of a variable that is either null or undefined.

let user = {
  name: "Alice",
  address: {
    street: "Main Street",
    city: "New York",
  },
  job: null
};

// TypeError: Cannot read properties of null
// console.log(user.job.name);

// TypeError: Cannot read properties of undefined
// console.log(user.x.y)

There is no definitive answer to when you should check if an object property is null, undefined, or exists, as it depends on the context and the purpose of your code. It’s critical to fully understand following methods before using any of them.

  1. Using typeof operator to check if a property is undefined. It will return "undefined" for both undefined and undeclared values, so it cannot tell if a property exists or not. It will return "object" for both null and object values, so it cannot distinguish between them.
let obj = {a: 1};
console.log(typeof obj); // "object"
console.log(typeof obj.a); // "number"
console.log(typeof obj.b); // "undefined"
console.log(typeof null); // "object"
  1. Using equality operators (==, ===) to check if property is null, undefined, or both.

The equality operator (==) will compare two values for equality after doing any necessary type conversions. This means that null and undefined are equal to each other, but not to anything else.

null == undefined // true
null == 0 // false
null == false // false
null == "" // false
undefined == 0 // false
undefined == false // false
undefined == "" // false

The strict equality operator (===) will compare two values for equality without doing any type conversion. This means that null and undefined are only equal to themselves, and not to any other value.

null === undefined // false
null === 0 // false
null === false // false
null === "" // false
undefined === 0 // false
undefined === false // false
undefined === "" // false

The strict equality operator is usually preferred over the equality operator, as it avoids unexpected results due to type coercion.

let person = {
  name: "Alice",
  age: null
};

console.log(person.name === null); // false
console.log(person.age === null); // true
console.log(person.address === null); // false
console.log(person.address === undefined); // true
  1. Using truthy/falsy evaluation (if statement, logical operator, ternary operator) to check if a property is null or undefined. Be aware that it will also treat other falsy values (such as false, 0, "", NaN) as equivalent.
const person = {
  name: "John Doe",
  age: 25,
  address: null,
  phone: undefined,
  email: "", // empty string
};

for (let prop in person) {
  if (person[prop]) {
    console.log(`${prop}: ${person[prop]}`);
  }
}

// name: John Doe
// age: 25
  1. Using Lodash _.isNil() function to check if object property is null or undefined.
var _ = require("lodash");

var obj = {
  name: "Charlie",
  age: 30,
  hobbies: ["cooking", "biking", "gardening"],
  address: null,
  score: 0,
  email: undefined
};

for (var prop in obj) {
  if (_.isNil(obj[prop])) {
    console.log(prop + ": " + obj[prop]);
  }
}

// address: null
// email: undefined
  1. Using in operator or hasOwnProperty method to check if a property exists. The in operator returns true if the property is found in the object or its prototype chain. The hasOwnProperty method returns true if the property is found in the object itself, and false if it is inherited or not found.
let obj = { prop1: "value1", prop2: undefined };

console.log("prop1" in obj); // true
console.log("prop2" in obj); // true
console.log("prop3" in obj); // false
console.log("toString" in obj); // true, inherited from Object.prototype

console.log(obj.hasOwnProperty("prop1")); // true
console.log(obj.hasOwnProperty("prop2")); // true
console.log(obj.hasOwnProperty("prop3")); // false
console.log(obj.hasOwnProperty("toString")); // false, inherited from Object.prototype

Using === or typeof to check undefined

Using === to check undefined is safe, as long as you are sure that the variable or property you are checking has been declared. However, if you try to access a variable or property that does not exist, you will get a ReferenceError.

// x is declared but not assigned a value
var x;
console.log(x === undefined); // true

// y is not declared
console.log(y === undefined); // ReferenceError: y is not defined

To avoid this error, you can use the typeof operator, which returns a string indicating the type of the operand. If the operand is undefined or not declared, it will return “undefined” as well.

// x is declared but not assigned a value
var x;
console.log(typeof x === "undefined"); // true

// y is not declared
console.log(typeof y === "undefined"); // true

Another reason to use typeof instead of === is that the global variable undefined can be overwritten in ES3, which can cause unexpected results when comparing with ===.

// In ES3, undefined can be redefined
window.undefined = "foo";
console.log("foo" === undefined); // true

// Using typeof is safer
console.log(typeof "foo" === "undefined"); // false

However, this issue has been fixed in ES5, and undefined is non-writable in modern browsers.

In combination with optional chaining

Accessing deeply nested properties is error prone, you need to check null and undefined on every step of the chain, not just the target property.

It’s recommended to using optional chaining (?.) to access properties or methods of a variable that might be null or undefined. This operator returns undefined if any part of the chain is null or undefined, instead of throwing an error.

let user = {
  name: "Alice",
  address: {
    street: "Main Street",
    city: "New York",
  },
};

// Without optional chaining, we need to check if user and user.address exist
console.log(user && user.address && user.address.street); // Main Street

// TypeError: Cannot read properties of undefined
// console.log(user.job.company);

// With optional chaining, we can write it more concisely
console.log(user?.address?.street); // Main Street
console.log(user?.job?.company); // undefined

You can use optional chaining in combination with truthy evaluation, equality operators, and typeof to check if a property value or nullish coalescing operator (??) to provide a default value.