在 JavaScript 中,in
运算符检查对象是否具有指定的属性。但是,它不仅检查对象自身的属性,还检查原型链。因此,在某些情况下,它的行为可能与预期不完全一样。
假设由于某种原因,我们有一个someArrayMethods
包含(显然)一些数组方法作为键的对象:
const someArrayMethods = {
indexOf: true,
map: true,
};
我们可以使用运算符检查该对象是否具有特定方法作为键in
:
console.log('indexOf' in someArrayMethods); // true
console.log('every' in someArrayMethods); // false
如果我们试图检查toString
财产怎么办?
console.log('toString' in someArrayMethods); // true
惊喜!事实证明,这个对象在原型链中有一个toString
方法,所以即使对象没有自己的属性,in
操作符也会返回。true
toString
这就是hasOwnProperty()
救援的地方!它与操作符几乎相同,但in
有一个区别:它不检查原型链。我们可以重写我们之前的例子:
console.log(someArrayMethods.hasOwnProperty('toString')); // false
现在它按预期工作。不幸的是,hasOwnProperty()
在一种情况下也可能失败。如果我们有一个拥有自己属性的对象hasOwnProperty
呢?看这个例子:
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...
为了解决这个问题,someObject.hasOwnProperty
我们可以直接引用该方法,而不是使用Object.prototype
:
const hasOwn = Object.prototype.hasOwnProperty;
console.log(hasOwn.call(someObject, 'theAnswer')); // true
这似乎是检查对象是否具有某些属性的最合理方法。尽管如此,是否存在in
操作员有用的情况?我知道它可以用来检查某个类的实例是否具有某种方法,但是在这种情况下,简单地检查该对象是否是该类的实例不是更好吗?
作为旁注,另一种选择是Object.keys()
与 ECMAScript 2016一起使用Array.prototype.includes()
:
console.log(Object.keys(someObject).includes('theAnswer')); // true