如果(键入对象)或如果(object.hasOwnProperty(键)

以下两个语句是否产生相同的输出? 有没有什么理由更喜欢一种方式?

if (key in object) if (object.hasOwnProperty(key)) 

小心 – 他们不会产生相同的结果。

in也会返回true如果key原型链的某个地方被find,而Object.hasOwnProperty (就像这个名字已经告诉我们的那样),只有在该对象可以直接使用key (它的“拥有”属性)时才会返回true

我试着用另一个例子来解释。 假设我们有以下两个属性的对象:

 function TestObj(){ this.name = 'Dragon'; } TestObj.prototype.gender = 'male'; 

让我们来创buildTestObj的实例:

 var o = new TestObj(); 

让我们来看看对象实例:

 console.log(o.hasOwnProperty('name')); // true console.log('name' in o); // true console.log(o.hasOwnProperty('gender')); // false console.log('gender' in o); // true 

结论:

  • in运算符总是返回true,如果属性可以被对象直接或从原型访问

  • hasOwnProperty()仅在实例上存在属性但不在其原型上时才返回true

如果我们要检查原型上是否存在某个属性,逻辑上,我们会说:

 console.log(('name' in o) && !o.hasOwnProperty('name')); //false console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype 

最后:

所以,关于这两个条件的说法…

 if (key in object) if (object.hasOwnProperty(key)) 

…产生相同的结果,答案是显而易见的,这取决于。

in也将检查inheritance的属性, hasOwnProperty不是这种情况。

总之,hasOwnProperty()不会在原型中寻找原型。

采取的formsO'Reilly高性能的Javascript :

您可以使用hasOwnProperty()方法并传入成员的名称来确定对象是否具有给定名称的实例成员。 要确定某个对象是否有权访问具有给定名称的属性,可以使用in运算符。 例如:

 var book = { title: "High Performance JavaScript", publisher: "Yahoo! Press" }; alert(book.hasOwnProperty("title")); //true alert(book.hasOwnProperty("toString")); //false alert("title" in book); //true alert("toString" in book); //true 

在这个代码中,hasOwnProperty()在传入“title”时返回true,因为title是一个对象实例; 当传入“toString”时,该方法返回false,因为它不存在于实例中。 当每个属性名称与in运算符一起使用时,结果两次都是真实的,因为它search实例和原型。

另一种forms(称为in)枚举对象的属性名称(或键)。 在每次迭代中,对象的另一个属性名称string被分配给variables。 通常需要testingobject.hasOwnProperty(variables)来确定属性名称是否是对象的成员,或者是在原型链上find的。

  for (myvar in obj) { if (obj.hasOwnProperty(myvar)) { ... } } 

(来自Crockford的Javascript:The Good Parts

你有一些非常好的答案。 我只是想提供一些东西,这将节省你迭代对象时检查“hasOwnProperty”的需要。

当创build一个对象时,通常人们会这样创build它:

 const someMap = {} // equivalent to: Object.create(Object.prototype) // someMap.constructor will yield -> function Object() { [native code] } 

现在,如果你想遍历“someMap”,你必须这样做:

 const key for(key in someMap ){ if (someMap.hasOwnProperty(key)) { // Do something } } 

我们这样做是为了避免遍历inheritance的属性。

如果您打算创build一个仅用作“地图”(即键 – 值对)的简单对象,您可以这样做:

 const newMap = Object.create(null); // Now, newMap won't have prototype at all. // newMap.constructor will yield -> undefined 

所以现在可以像这样迭代:

 for(key in cleanMap){ console.log(key + " -> " + newMap [key]); // No need to add extra checks, as the object will always be clean } 

我在这里学到了这个真棒技巧

第一个版本更短(尤其是在variables被重命名的缩小代码中)

 a in b 

VS

 b.hasOwnProperty(a) 

无论如何,正如@AndreMeinhold所说的,他们并不总是产生同样的结果。