以下两个语句是否产生相同的输出?有什么理由更喜欢一种方式而不是另一种方式吗?
if (key in object)
if (object.hasOwnProperty(key))
以下两个语句是否产生相同的输出?有什么理由更喜欢一种方式而不是另一种方式吗?
if (key in object)
if (object.hasOwnProperty(key))
小心——它们不会产生相同的结果。
in
true
如果在原型链key
中的某处找到也将返回,而(就像名称已经告诉我们的那样),只有在该对象直接可用时才会返回(它“拥有”该属性)。Object.hasOwnProperty
true
key
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.
in
还将检查继承的属性,而hasOwnProperty
.
综上所述,hasOwnProperty()
不看原型而in
只看原型。
您可以通过使用 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 运算符一起使用时,结果都为真,因为它搜索实例和原型。
你得到了一些非常好的答案。我只想提供一些东西,让您在迭代对象时无需检查“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
}
我在这里学到了这个很棒的技巧
另一种形式(调用 in)枚举对象的属性名称(或键)。在每次迭代中,来自对象的另一个属性名称字符串被分配给变量。通常需要测试 object.hasOwnProperty(variable) 以确定属性名称是否真的是对象的成员,或者是在原型链上找到的。
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(来自 Crockford 的Javascript: The Good Parts)
正如其他答案所表明的那样,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
第一个版本更短(特别是在变量被重命名的缩小代码中)
a in b
对比
b.hasOwnProperty(a)
无论如何,正如@AndreMeinhold 所说,它们并不总是产生相同的结果。