Michał Perłakowski
Michał Perłakowski

Reputation: 92521

Are there any cases when I should use the in operator instead of hasOwnProperty()?

In JavaScript the in operator checks whether an object has the specified property. However, it doesn't check only object's own properties, but also the prototype chain. Therefore in some situations it may behave not exactly as expected.

Let's say that for some reason we have an object someArrayMethods containing (obviously) some array methods as keys:

const someArrayMethods = {
  indexOf: true,
  map: true,
};

We can check if that object has a specific method as a key using the in operator:

console.log('indexOf' in someArrayMethods); // true
console.log('every' in someArrayMethods); // false

What if we tried to check for toString property?

console.log('toString' in someArrayMethods); // true

Surprise! It turns out that this object has a toString method in the prototype chain, so the in operator returns true even though the object doesn't have its own toString property.

And here's where hasOwnProperty() comes to the rescue! It's almost the same as the in operator, with one difference: it doesn't check the prototype chain. We can rewrite our previous example:

console.log(someArrayMethods.hasOwnProperty('toString'));  // false

Now it works as expected. Unfortunately, hasOwnProperty() also can fail in one case. What if we had an object with an own property hasOwnProperty? See this example:

const someObject = {
  hasOwnProperty() {
    return false;
  },
  theAnswer: 42,
};

// Does `someObject` has own property `theAnswer`?
console.log(someObject.hasOwnProperty('theAnswer')); // false
// Well, it seems it doesn't...

To solve this problem, instead of using someObject.hasOwnProperty, we can refer to that method directly from Object.prototype:

const hasOwn = Object.prototype.hasOwnProperty;
console.log(hasOwn.call(someObject, 'theAnswer')); // true

This seems to be the most reasonable approach for checking if an object has some property. Despite this, are there any cases where the in operator would be useful? I know that it can be used to check if an instance of some class has some method, but in this case isn't it better to simply check if that object is an instance of that class?


As a side note, another option is to use Object.keys() with ECMAScript 2016 Array.prototype.includes():

console.log(Object.keys(someObject).includes('theAnswer')); // true

Upvotes: 3

Views: 991

Answers (3)

AM Douglas
AM Douglas

Reputation: 1903

Feature detection for loading polyfills, testing conditions for using modern DOM APIs etc.

Using the in operator is ideal for assessing whether you should load/execute a JavaScript polyfill precisely because it checks the prototype chain.

For instance:

// this works wonderfully
if (!('addEventListener' in window)) {
  // polyfill addEventListener
}

compared to:

// this doesn't work at all
if (!window.hasOwnProperty('addEventListener')) {
  // polyfill addEventListener
}

Hence why the Polyfill.io service uses it for its feature detection tests.

Upvotes: 3

Oriol
Oriol

Reputation: 288260

in is an operator, so it can't be hijacked. You don't have to rely on that no script altered or shadowed Object, Object.prototype, Object.prototype.hasOwnProperty, Object.prototype.hasOwnProperty.call.

And it's a fast way to know if an object has some property. I mean, if obj.foo can return e.g. "bar" even if the foo property is inherited, it makes sense to be able to know if obj has that foo property or not beforehand, either own or inherited.

Sure, if we only had HasOwnProperty, we could (usually) keep calling [[GetPrototypeOf]] until the end of the chain, and check each object. But that would be tedious to code, probably slower than a native in, and not possible before ES5.

Moreover, there is a fundamental difference. The in operator uses the [[HasProperty]] internal method, while HasOwnProperty uses [[GetOwnProperty]]. Iterating [[GetOwnProperty]] and [[GetPrototypeOf]] may produce a different result than [[HasProperty]] for non-ordinary objects.

So yes: the in operator is useful when you want to call the internal [[HasProperty]] method of an object. In fact, apart from Reflect.has, it is the only proper way to do that.

var p = new Proxy({}, {has: function() {
  console.log('Hooray!');
  return true;
}});
p.hasOwnProperty('foo'); // :(
'foo' in p; // Hooray! :)

Upvotes: 5

Jocky Doe
Jocky Doe

Reputation: 2161

You answer your own question. in is good when you want to search in prototype chain as well.

Upvotes: 4

Related Questions