最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin1浏览0评论

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() es 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

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() es 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
Share Improve this question asked Oct 31, 2016 at 2:19 Michał PerłakowskiMichał Perłakowski 92.9k30 gold badges163 silver badges187 bronze badges 1
  • In most cases if a function accepts something with some property - it should not be its business where in the prototype chain the property is defined, but that it's just available. That way you separate the data shape from the implementation details. – zerkms Commented Oct 31, 2016 at 2:23
Add a ment  | 

3 Answers 3

Reset to default 5

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! :)

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

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
}

pared 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.

发布评论

评论列表(0)

  1. 暂无评论