Checking whether a property exists in an object
You check for a property with the in operator, the hasOwnProperty() method, the Object.hasOwn() function, or by comparing the value with undefined. These options are not interchangeable: they treat the prototype differently and they react differently to a property whose value is undefined.
Theory
TL;DR
'key' in objis the most universal option: it returnstruefor own properties and for ones inherited from the prototype.obj.hasOwnProperty('key')checks own properties only and ignores the prototype, the classic approach.Object.hasOwn(obj, 'key')is the modern standard from ES2022: the same semantics ashasOwnProperty, but more robust.obj.key !== undefinedchecks the value rather than the key, so it lies when the value really isundefined.- Short rule: need every property, use
in; need own properties only, useObject.hasOwn.
Quick example
const user = { name: 'Maria', age: 25 };
console.log('age' in user); // true
console.log('city' in user); // false
console.log(user.hasOwnProperty('age')); // true
console.log(Object.hasOwn(user, 'city')); // falseThe in operator, the most universal way
const user = { name: 'Maria', age: 25 };
console.log('age' in user); // true
console.log('city' in user); // falseThe operator checks whether the key exists in the object, including properties inherited from the prototype. The left side is a string or a Symbol, the right side is the object itself.
An example with inheritance:
const person = { species: 'human' };
const user = Object.create(person);
user.name = 'Maria';
console.log('species' in user); // true (inherited)species is not stored on user directly, but it lives on its prototype person, so in returns true. This is also why 'toString' in {} is true: the method comes from Object.prototype.
hasOwnProperty(), own properties only
const user = { name: 'Maria', age: 25 };
console.log(user.hasOwnProperty('age')); // true
console.log(user.hasOwnProperty('city')); // falseUnlike in, the method ignores the prototype and looks only at properties that are really defined on the object itself.
The difference in practice:
const person = { species: 'human' };
const user = Object.create(person);
user.name = 'Maria';
console.log('species' in user); // true
console.log(user.hasOwnProperty('species')); // falseObject.hasOwn(), the modern counterpart of hasOwnProperty
ES2022 added a safer and more readable form:
const user = { name: 'Maria' };
console.log(Object.hasOwn(user, 'name')); // true
console.log(Object.hasOwn(user, 'city')); // falseIt works exactly like hasOwnProperty, but it does not depend on what happens inside the object itself. Two cases where hasOwnProperty breaks and Object.hasOwn does not:
// 1. An object with no prototype simply has no hasOwnProperty method.
const dict = Object.create(null);
dict.token = 1;
// dict.hasOwnProperty('token'); // TypeError
console.log(Object.hasOwn(dict, 'token')); // true
// 2. An own property with the same name shadows the method.
const data = { hasOwnProperty: () => false, id: 7 };
console.log(data.hasOwnProperty('id')); // false, overridden
console.log(Object.hasOwn(data, 'id')); // trueComparing with undefined, the simplest but not always accurate way
const user = { name: 'Maria' };
if (user.age !== undefined) {
console.log('The age property exists');
} else {
console.log('There is no age property');
}The downside: if the property does exist but holds undefined, you get a false negative.
const user = { age: undefined };
console.log(user.age !== undefined); // false, although the key existsThe shorter if (user.age) check is wrong for the same reason: it discards 0, '', null and false, which are perfectly valid values.
Comparison of the options
| Option | What it checks | Sees the prototype | Reliability |
|---|---|---|---|
'key' in obj | whether the key exists | Yes | Excellent choice |
obj.hasOwnProperty('key') | own properties only | No | Classic |
Object.hasOwn(obj, 'key') | own properties only | No | Modern standard |
obj.key !== undefined | value is not undefined | No | Can be misleading |
To check whether an object has a property, use
'key' in objwhen every property counts, inherited ones included, orObject.hasOwn(obj, 'key')when you need own properties only.
Common mistakes
- Confusing the key with its value.
obj.key !== undefinedreturnsfalsefor a property that exists and holdsundefined. Check the key withinorObject.hasOwn. - Shortening it to
if (obj.key). The values0,'',null,NaNandfalseare falsy, so existing properties get silently skipped. - Forgetting the prototype. The
inoperator also seestoString,constructorand other inherited members, so for data that came from outside preferObject.hasOwn. - Calling
hasOwnPropertyon anObject.create(null)object. Such an object has no prototype, so the method is missing and the call throws aTypeError. - Trusting
hasOwnPropertyon user input. Incoming JSON may carry its ownhasOwnPropertykey and shadow the method.Object.hasOwnorObject.prototype.hasOwnProperty.call(obj, key)are immune to that. - Writing
inwith a variable name instead of a string.key in objchecks the value of the variablekey, while'key' in objchecks the literal key"key". These are two different checks.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.