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.missingreturnsundefined, it does not throw.- Dynamic access
obj[key]behaves exactly the same way. - A
TypeErrorshows 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 needinorhasOwnProperty.
Quick example
const user = { name: 'Maria' };
console.log(user.name); // "Maria"
console.log(user.age); // undefined
console.log(user.address); // undefinedJavaScript does not raise an error, it simply returns undefined.
Why undefined is returned
When reading a property, the engine does the following:
- Checks whether the property exists on the object itself.
- If it does, returns its value.
- If it does not, keeps looking up the prototype chain.
- If it is nowhere to be found, returns
undefined.
user.hasOwnProperty('age'); // false
user.age; // undefinedThis 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:
console.log(user.address.city); // TypeErrorThe 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.
if (user.address && user.address.city) {
console.log(user.address.city);
}Option 2. Optional chaining ?. (the modern approach).
console.log(user.address?.city); // undefined, but with no errorIf 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 ??.
console.log(user.address?.city ?? 'Not specified');
// "Not specified"Dynamic access and existence checks
With square brackets the behaviour is identical:
const key = 'email';
console.log(user[key]); // undefined, when the property is absentThe 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:
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 formin also counts properties inherited from the prototype, while hasOwnProperty and Object.hasOwn count only own ones.
Summary tables
| Situation | Result | Explanation |
|---|---|---|
user.age | undefined | the property is absent |
user.age.city | TypeError | undefined is not an object |
'age' in user | false | an existence check |
user.hasOwnProperty('age') | false | a check for own properties only |
user.name ?? 'none' | 'Maria' | the value is returned |
user.age ?? 'none' | 'none' | the default value is substituted |
| Behaviour | What happens | |
| --- | --- | |
obj.missing | returns undefined | |
| No error | even when the property does not exist | |
| An error appears | when trying to go deeper (undefined.city) | |
| The fix | use ?. or ?? |
An example to tie it together:
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); // TypeErrorCommon 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, anddata.user.profile.avatarbreaks at the first missing level. - Putting
?.only at the end of the chain.user.address?.citydoes not help whenuseritself may beundefined. That needsuser?.address?.city. - Confusing "no such property" with "the value is
undefined". The comparisonobj.key === undefinedcannot distinguish the two, which is whatinandObject.hasOwnare for. - Calling a method that does not exist.
obj.doSomething()throwsTypeError: obj.doSomething is not a function, becauseundefinedcannot be called. The safe form isobj.doSomething?.().
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.