197

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

 if (key in object)

 if (object.hasOwnProperty(key))
4

8 回答 8

200

小心——它们不会产生相同的结果。

intrue如果在原型链key中的某处找到也将返回,而(就像名称已经告诉我们的那样),只有在该对象直接可用时才会返回(它“拥有”该属性)。Object.hasOwnPropertytruekey

于 2012-11-29T19:16:03.697 回答
75

I'l try to explain with another example. Say we have the following object with two properties:

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

Let's create instance of TestObj:

var o = new TestObj();

Let's examine the object instance:

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

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

Conclusion:

  • in operator returns true always, if property is accessible by the object, directly or from the prototype

  • hasOwnProperty() returns true only if property exists on the instance, but not on its prototype

If we want to check that some property exist on the prototype, logically, we would say:

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

Finally:

So, regarding to statement that these two conditions ...

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

...produce the same result, the answer is obvious, it depends.

于 2014-11-28T14:10:57.387 回答
33

in还将检查继承的属性,而hasOwnProperty.

于 2012-11-29T19:15:53.223 回答
32

综上所述,hasOwnProperty()不看原型而in只看原型。

取自O'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

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

于 2015-04-23T15:06:17.790 回答
10

你得到了一些非常好的答案。我只想提供一些东西,让您在迭代对象时无需检查“hasOwnProperty”。

在创建对象时,人们通常会以这种方式创建它:

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
 }
}

我们这样做是为了避免迭代继承的属性。

如果您打算创建一个仅用作“映射”(即键-值对)的简单对象,您可以这样做:

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
}

我在这里学到了这个很棒的技巧

于 2017-09-01T22:36:25.203 回答
2

另一种形式(调用 in)枚举对象的属性名称(或键)。在每次迭代中,来自对象的另一个属性名称字符串被分配给变量。通常需要测试 object.hasOwnProperty(variable) 以确定属性名称是否真的是对象的成员,或者是在原型链上找到的。

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

(来自 Crockford 的Javascript: The Good Parts

于 2012-11-29T19:18:09.350 回答
1

正如其他答案所表明的那样,hasOwnProperty将检查对象自身的属性,相比之下in,还将检查继承的属性。

新方法 2021 - Object.hasOwn()作为替代Object.hasOwnProperty()

Object.hasOwn()旨在替代Object.hasOwnProperty()并且是一种可供使用的新方法(但仍未得到所有浏览器的完全支持,如您在此处看到的 - https://caniuse.com/?search=hasOwn

Object.hasOwn()是一个静态方法,如果指定对象具有指定属性作为其自己的属性,则返回 true。如果属性被继承或不存在,则该方法返回 false。

const person = { name: 'dan' };

console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false

const person2 = Object.create({gender: 'male'});

console.log(Object.hasOwn(person2, 'gender'));// false

建议使用此方法,Object.hasOwnProperty()因为它也适用于通过 using 创建的Object.create(null)对象和覆盖了继承hasOwnProperty()方法的对象。虽然可以通过调用Object.prototype.hasOwnProperty()外部对象来解决这类问题,但要Object.hasOwn() 克服这些问题,因此是首选(参见下面的示例)

let person = {
  hasOwnProperty: function() {
    return false;
  },
  age: 35
};

if (Object.hasOwn(person, 'age')) {
  console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
}

let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
  console.log(person.age); // true - works regardless of how the object was created
}

更多信息Object.hasOwn可以在这里找到:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

浏览器兼容性 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility

于 2021-10-22T12:16:45.923 回答
-5

第一个版本更短(特别是在变量被重命名的缩小代码中)

a in b

对比

b.hasOwnProperty(a)

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

于 2012-11-29T19:15:58.473 回答