Ian Kim

Checking if a property exists on a JavaScript object


Here are the various ways to check if a property exists on an object:

For cases where myObject is an object literal that we make ourselves, these methods all return the same thing:

const myObject = {
  foo: "bar",
  meaningOfLife: 42,
};

> myObject.hasOwnProperty("foo");
true
> Object.prototype.hasOwnProperty.call(myObject, "foo");
true
> Object.hasOwn(myObject, "foo");
true
> myObject["foo"] != null;
true
> myObject.foo != null;
true
> "foo" in myObject;
true

So if they all return the same thing, which one should we use? In order to answer that question, we need to talk about the JavaScript prototype chain.

Prototype-based inheritance

JavaScript has a prototype based inheritance system, where rather than having a class definition that acts as a template, objects have a prototype that is another concrete object. (That is, there is no distinction between a class definition and a class instance in the prototype-based model.) It’s objects all the way down!

(Note that JavaScript as of ES5 has a notion of classes, but these are really syntactic sugar around the prototype model.)

The object literal syntax const foo = { someProperty: "someValue" } always inherits from a prototype named Object.prototype; similarly,

const someObject = { someProperty: "someValue" };
const someArray = [];
const someString = "hello, world";
const someRegexp = /.*/;

> Object.getPrototypeOf(someObject) === Object.prototype
true
> Object.getPrototypeOf(someArray) === Array.prototype
true
> Object.getPrototypeOf(someString) === String.prototype
true
> Object.getPrototypeOf(someRegexp) === RegExp.prototype
true

Prototypes can be changed, even after object creation

The prototype of an object can be changed by:

This can be done after the object has already been created:

const bar = { barProperty: 123 };
const foo = { fooProperty: 456 };

> foo.barProperty
undefined

foo.__proto__ = bar;
> foo.barProperty
123

Importantly, because prototypes are themselves objects, they can always be modified later. Yes, even Object.prototype!

const foo = { fooProperty: 456 };

> foo.barProperty
undefined

Object.prototype.barProperty = 123;
> foo.barProperty
123

Hopefully this goes without saying: even if you’re allowed do it, please don’t change Object.prototype! It will affect every object literal.

The prototype chain

A prototype can also have a prototype of its own:

const parent = { parentProperty: 'abc' };
const child = {
  childProperty: 'def',
  __proto__: parent
};

> Object.getPrototypeOf(child) === parent
true
> Object.getPrototypeOf(parent) === Object.prototype
true
> Object.getPrototypeOf(Object.prototype)
null

The term “prototype chain” comes from the act of following the prototype of an object, then the prototype of that prototype, and so on until null is reached, which does not have a prototype and acts as the end of the prototype chain. In this example, the prototype chain starting from child is:

childparentObject.prototypenull (end of prototype chain)

Own properties vs. inherited properties

When we are asking if an object has a property, the JavaScript runtime might ask us back: “do you want to check inherited properties too?”

Properties that are inherited are, well, inherited properties, while properties that are not inherited are called own properties.

And when we try to access a property on an object using myObject.someProperty, we’re checking not just the object’s own properties, but all of its inherited properties too. This is called climbing up the prototype chain:

JavaScript objects are dynamic “bags” of properties (referred to as own properties). JavaScript objects have a link to a prototype object. When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.

Retrying the test with inherited properties

What if our object literal inherited from another object? We’ll create a customPrototype object that inherits from Object.prototype, then make myObject inherit from customPrototype:

const customPrototype = {
  baz: 500,
};

const myObject = {
  foo: "bar",
  meaningOfLife: 42,
  __proto__: customPrototype,
};

> Object.getPrototypeOf(myObject) === customPrototype;
true

And now let’s see what happens when we check each method against the property baz, which only exists on customPrototype and not in myObject:

> myObject.hasOwnProperty('baz')
false
> Object.prototype.hasOwnProperty.call(myObject, 'baz')
false
> Object.hasOwn(myObject, 'baz')
false
> myObject['baz'] != null
true
> myObject.baz != null
true
> 'baz' in myObject
true

Checking for own properties

So based on the above results, we can see that the following methods check if the property is present either on the object itself (an own property) or anywhere in its prototype chain (an inherited property):

While these methods only check if the property is an own property:

The difference between these 3 own property checks

A natural question you’d ask is, what’s the difference between these three methods? Don’t they all check if the property is an own property?

Unfortunately, hasOwnProperty is not protected by JavaScript, which means that an object can redefine it to e.g. always return false (or if you’re truly malevolent, the opposite of what you would expect):

const foo = {
  hasOwnProperty() {
    return false;
  },
  fooProperty: 123,
};

foo.hasOwnProperty("fooProperty");
> false

// or even more evil
const bar = {
  hasOwnProperty(key) {
    return !Object.prototype.hasOwnProperty.call(this, key);
  },
  barProperty: 123,
};

bar.hasOwnProperty("barProperty");
> false
bar.hasOwnProperty("shouldNotExist");
> true

To work around the possibility of an object redefining hasOwnProperty, we can use Object.prototype.hasOwnProperty.call(myObject, "someProperty") instead, which is a bit safer [1]:

const foo = {
  hasOwnProperty() {
    return false;
  },
  fooProperty: 123,
};

foo.hasOwnProperty("fooProperty");
> false
Object.prototype.hasOwnProperty.call(foo, "fooProperty")
> true

const bar = {
  hasOwnProperty(key) {
    return !Object.prototype.hasOwnProperty.call(this, key);
  },
  barProperty: 123,
};

bar.hasOwnProperty("barProperty");
> false
Object.prototype.hasOwnProperty.call(bar, "barProperty");
> true

bar.hasOwnProperty("shouldNotExist");
> true
Object.prototype.hasOwnProperty.call(bar, "shouldNotExist");
> false

Since this is rather verbose and inconvenient, Object.hasOwn was introduced as a replacement for Object.prototype.hasOwnProperty, because it cannot be overridden:

const foo = {
  hasOwn() {
    // this doesn't affect Object.hasOwn at all
    return false;
  },
  fooProperty: 123,
};

Object.hasOwn(foo, "fooProperty");
> true

So Object.hasOwn allows us to avoid this potential pitfall [2]. The downside is that it was added relatively recently, so only more recent browsers support it: Chrome 93+, Edge 93+, Safari 15.4+, Firefox 92+, and no support for it in IE11. (You could of course transpile or polyfill Object.hasOwn if needed.)

Conclusion: what do I use?

If you’re only interested in own properties (in my experience, almost always what you actually want):

If you want to check all properties, including inherited properties, use any of the following:

Can I use indexing or in for own properties anyway?

If you are positive that

  1. myObject is an object literal that inherits only from Object.prototype, and
  2. no other code is modifying Object.prototype,

then indexing or in will also return the expected result.

It should be noted that even in these cases, if someProperty isn’t an own property of myObject, indexing or using in will still climb up the prototype chain and check properties unnecessarily, so using Object.hasOwn is preferred.


[1] Note that I said a bit safer, since even Object.prototype.hasOwnProperty can be redefined…

Object.prototype.hasOwnProperty = () => false;
const foo = { bar: 123 };

> Object.prototype.hasOwnProperty(foo, "bar");
false

[2] Unfortunately, yes, Object.hasOwn can be redefined too:

Object.hasOwn = () => false;
const foo = { bar: 123 };

> Object.hasOwn(foo, "bar");
false