Checking whether a property exists in an object
JavaScript gives you several ways to check whether an object has a given property, and each one behaves slightly differently. The difference is whether the prototype chain is taken into account and whether a value of undefined can fool the check.
Theory
TL;DR
'key' in objchecks that the property exists, including properties inherited from the prototype.obj.hasOwnProperty('key')sees own properties only, but the method can be overridden.Object.hasOwn(obj, 'key')(ES2022) is the modern, safe replacement forhasOwnProperty().obj.key !== undefinedchecks the value, not the existence, so it is wrong for properties whose value isundefined.Reflect.has(obj, 'key')behaves exactly likeinand is convenient in metaprogramming code.
Quick example
const user = { name: 'Alice', age: 25 };
console.log('name' in user); // true
console.log(Object.hasOwn(user, 'name')); // true
console.log('email' in user); // falseThe in operator
The most direct and reliable way to check that a property exists at all.
const user = { name: 'Alice', age: 25 };
console.log('name' in user); // true
console.log('email' in user); // falseThe operator takes the whole prototype chain into account:
const person = { isHuman: true };
const user = Object.create(person);
user.name = 'Alice';
console.log('name' in user); // true, own property
console.log('isHuman' in user); // true, inheritedThe hasOwnProperty() method
It checks own properties only, that is, the ones that really belong to the object itself and not to its prototype.
const person = { isHuman: true };
const user = Object.create(person);
user.name = 'Alice';
console.log(user.hasOwnProperty('name')); // true
console.log(user.hasOwnProperty('isHuman')); // falseUse it when you need to be sure a property is defined on the object itself rather than inherited.
Careful: if someone has overridden
hasOwnProperty, or the object was created withObject.create(null)and therefore has no prototype, call the method like this:
Object.prototype.hasOwnProperty.call(user, 'name');The Object.hasOwn() method
The modern version of hasOwnProperty from ES2022, safer because it does not depend on the object's own prototype chain.
const user = { name: 'Alice' };
console.log(Object.hasOwn(user, 'name')); // true
console.log(Object.hasOwn(user, 'email')); // falseIn new code Object.hasOwn() is the recommended choice over hasOwnProperty().
Checking against undefined
A simple but not always safe approach:
const user = { name: 'Alice' };
console.log(user.name !== undefined); // true
console.log(user.email !== undefined); // falseThe problem is that a property may exist and still hold the value undefined:
const user = { name: undefined };
console.log('name' in user); // true, the property is there
console.log(user.name !== undefined); // false, the check misleads youReflect.has() and a comparison of the approaches
One more option, from the Reflect API:
const user = { name: 'Alice' };
console.log(Reflect.has(user, 'name')); // true
console.log(Reflect.has(user, 'email')); // falseIt works exactly like in, but is convenient in reflective, metaprogramming code, for example inside a Proxy has trap.
| Method | Sees inherited | Own only | Safe for any object | Example |
|---|---|---|---|---|
'key' in obj | yes | no | yes | 'name' in user |
obj.hasOwnProperty('key') | no | yes | not always, the method can be overridden | user.hasOwnProperty('name') |
Object.hasOwn(obj, 'key') | no | yes | yes | Object.hasOwn(user, 'name') |
obj.key !== undefined | not always | no | yes | user.name !== undefined |
| Goal | Best approach | |||
| --- | --- | |||
| Check any property, including inherited ones | 'prop' in obj | |||
| Check an own property only | Object.hasOwn(obj, 'prop') | |||
| Support for old browsers | obj.hasOwnProperty('prop') | |||
Check that the value is not undefined | obj.key !== undefined, with care |
Common mistakes
- Checking existence with
!== undefined. A property whose value isundefineddoes exist, yet this check returnsfalse. - Using
if (obj.count)as an existence check.0,'',falseandnullare falsy too, so a present field looks missing. - Calling
hasOwnPropertydirectly on an object fromObject.create(null). There is no prototype, so the method is unavailable and you get aTypeError; useObject.hasOwn(). - Confusing
inwith iteration. For arraysinchecks the index, not the value:1 in [10, 20]istrue, while20 in [10, 20]isfalse. - Forgetting inherited fields.
'toString' in {}istrue, because the method comes fromObject.prototype. - Thinking
?.replaces the check.user?.emailonly guards against an error onnull; it does not distinguish a missing field from a field holdingundefined.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.