Object.prototype.hasOwnProperty()

Superseded by Object.hasOwn in ES2022, for one reason: being a method, it can be missing or replaced on the object you are asking about.

Object methodES3 (1999)Live demo
Common call
Object.hasOwn(o, key)
Returns
boolean
Replaces
nothing — Object.hasOwn replaces IT
Watch out
unsafe on parsed JSON and null-prototype objects
object.hasOwnProperty(keykey — The property key. Non-symbols are coerced to strings, so 1 and "1" are the same key.type: string | symbol · required)
→ boolean

Demo

Live evaluation
Try:
Inputs
jsonstringa JSON object
keystringproperty name
Output
JSON.parse('{"a":1}').hasOwnProperty('a')
true

The results match Object.hasOwn exactly — inherited properties are false, and a property whose value is null still counts as present. What the demo cannot show is the failure mode that made this method obsolete: it only works because the object inherits it from Object.prototype. Give the object a property of the same name, or create it with no prototype at all, and the call throws instead of answering.

Parameters

NameTypeRequiredDescription
keystring | symbolyesThe property key. Non-symbols are coerced to strings, so 1 and "1" are the same key.

Return value

boolean — True if the key is an own property. Inherited properties give false — which is the entire point of it.

Common patterns

Use the static form
Cannot be shadowed or missing.
if (Object.hasOwn(o, key)) { }
The safe legacy form
For runtimes before ES2022.
if (Object.prototype.hasOwnProperty.call(o, key)) { }
Guard a for...in loop
The historical reason this method is everywhere.
for (const k in o) {
  if (!Object.hasOwn(o, k)) continue;
}

Examples

1. Own property
({a: 1}).hasOwnProperty("a")
Returns
true
2. Inherited
({}).hasOwnProperty("toString")
Returns
false
3. in disagrees
"toString" in {}
Returns
true
4. Null-prototype throws
Object.create(null).hasOwnProperty("a")
Returns
TypeError: ...hasOwnProperty is not a function
5. Shadowed throws
JSON.parse('{"hasOwnProperty":1}').hasOwnProperty("x")
Returns
TypeError: ...hasOwnProperty is not a function
6. The static is fine
Object.hasOwn(Object.create(null), "a")
Returns
false

Pitfalls

1. It can be shadowed by the data
Any object with its own hasOwnProperty property replaces the method. Parsed JSON, query strings and form data can all contain that key, so the call throws — or, if the value happens to be callable, returns whatever the attacker decided.
Broken by data
JSON.parse('{"hasOwnProperty":1}').hasOwnProperty("x")
TypeError: ...hasOwnProperty is not a function
Static form
Object.hasOwn(JSON.parse('{"hasOwnProperty":1}'), "x")
false
2. It does not exist on null-prototype objects
The method is inherited from Object.prototype, so an object created with Object.create(null) — the standard way to build a safe dictionary — simply does not have it.
Not a function
Object.create(null).hasOwnProperty("a")
TypeError: ...hasOwnProperty is not a function
Object.hasOwn
Object.hasOwn(Object.create(null), "a")
false
3. Linters flag direct calls for exactly this reason
The ESLint rule no-prototype-builtins exists because of the two problems above. The historical fix was the verbose borrowed call; the modern one is the static method.
Rule violation
o.hasOwnProperty(k)
no-prototype-builtins
Either safe form
Object.hasOwn(o, k)
passes
4. It is not the in operator
in searches the whole prototype chain; this stops at own properties. Neither is wrong — they answer different questions — but swapping one for the other changes the behaviour for every inherited method.
Misses inherited
class A { m() {} }
new A().hasOwnProperty("m")
false
in finds it
"m" in new A()
true

When to use

Use it
  • Legacy code where it already appears and the objects are trusted
  • Runtimes predating ES2022, via the borrowed-call form
Reach for something else
  • New code → Object.hasOwn
  • Objects from untrusted input → the static form, always
  • Null-prototype dictionaries → the method does not exist there
  • You want inherited properties too → the in operator

Notes

Complexity
O(1) — an own-property lookup with no chain walk
Return
A boolean; nothing is allocated
CPython impl
V8: Builtins-object-hasownproperty
Memory
No allocation
Thread-safe
Single-threaded; the object is only read

FAQ

Not in new code. Object.hasOwn does the same job, cannot be shadowed by the object being tested, and works on null-prototype objects. The only reason to keep the old form is a runtime older than 2021, and even then the borrowed call is safer than the direct one.

Object.hasOwn(o, k);                          // modern
Object.prototype.hasOwnProperty.call(o, k);   // safe legacy

History

ES3
hasOwnProperty present from early JavaScript as the for...in guard.
ES5
Object.create(null) made prototype-less objects common, and this method unavailable on them.
ES2022
Object.hasOwn added as the static, un-shadowable replacement.