Skip to main content

Accessing a non-existent object property

If you access a property that does not exist on an object, nothing is thrown and the result is undefined. An error appears only when that undefined is then treated as an object and one of its own properties is read.

Theory

TL;DR

  • obj.missing returns undefined, it does not throw.
  • Dynamic access obj[key] behaves exactly the same way.
  • A TypeError shows up at the next step of the chain: undefined.city.
  • Safe options: a manual && check, optional chaining ?., and a default value via ??.
  • To tell "the property is absent" from "the property is undefined" you need in or hasOwnProperty.

Quick example

javascript
const user = { name: 'Maria' }; console.log(user.name); // "Maria" console.log(user.age); // undefined console.log(user.address); // undefined

JavaScript does not raise an error, it simply returns undefined.

Why undefined is returned

When reading a property, the engine does the following:

  1. Checks whether the property exists on the object itself.
  2. If it does, returns its value.
  3. If it does not, keeps looking up the prototype chain.
  4. If it is nowhere to be found, returns undefined.
javascript
user.hasOwnProperty('age'); // false user.age; // undefined

This is a deliberate language decision: a missing property is not an error condition but an ordinary state of the data.

When an error does occur

The error appears when you go further down the chain:

javascript
console.log(user.address.city); // TypeError

The reason: user.address is undefined, and properties cannot be requested from undefined. In a browser the message looks roughly like TypeError: Cannot read properties of undefined (reading 'city').

The same applies to null: neither value has an object wrapper, so any property read on them fails.

How to read nested properties safely

Option 1. Manual checks.

javascript
if (user.address && user.address.city) { console.log(user.address.city); }

Option 2. Optional chaining ?. (the modern approach).

javascript
console.log(user.address?.city); // undefined, but with no error

If the value to the left of ?. is null or undefined, JavaScript stops evaluating the whole chain and returns undefined.

Option 3. A default value via ??.

javascript
console.log(user.address?.city ?? 'Not specified'); // "Not specified"

Dynamic access and existence checks

With square brackets the behaviour is identical:

javascript
const key = 'email'; console.log(user[key]); // undefined, when the property is absent

The catch is that undefined also comes back when the property does exist but its value is undefined. Telling those two cases apart requires separate checks:

javascript
const account = { email: undefined }; account.email; // undefined 'email' in account; // true, the property exists account.hasOwnProperty('email'); // true, and it is an own property Object.hasOwn(account, 'email'); // true, the modern form

in also counts properties inherited from the prototype, while hasOwnProperty and Object.hasOwn count only own ones.

Summary tables

SituationResultExplanation
user.ageundefinedthe property is absent
user.age.cityTypeErrorundefined is not an object
'age' in userfalsean existence check
user.hasOwnProperty('age')falsea check for own properties only
user.name ?? 'none''Maria'the value is returned
user.age ?? 'none''none'the default value is substituted
BehaviourWhat happens
------
obj.missingreturns undefined
No erroreven when the property does not exist
An error appearswhen trying to go deeper (undefined.city)
The fixuse ?. or ??

An example to tie it together:

javascript
const user = { name: 'Maria' }; console.log(user.age); // undefined console.log(user.age?.value); // undefined (no error) console.log(user.age ?? 'none'); // "none" console.log(user.age.value); // TypeError

Common mistakes

  • Expecting an error where there is none. A typo in a property name quietly yields undefined, and the bug surfaces much later, somewhere else in the code.
  • Reading a deep chain without ?.. API data often arrives incomplete, and data.user.profile.avatar breaks at the first missing level.
  • Putting ?. only at the end of the chain. user.address?.city does not help when user itself may be undefined. That needs user?.address?.city.
  • Confusing "no such property" with "the value is undefined". The comparison obj.key === undefined cannot distinguish the two, which is what in and Object.hasOwn are for.
  • Calling a method that does not exist. obj.doSomething() throws TypeError: obj.doSomething is not a function, because undefined cannot be called. The safe form is obj.doSomething?.().

Short Answer

Interview ready
Premium

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