下面两个语句产生相同的输出吗?我们有理由选择其中一种方式而不是另一种吗?
if (key in object)
if (object.hasOwnProperty(key))
下面两个语句产生相同的输出吗?我们有理由选择其中一种方式而不是另一种吗?
if (key in object)
if (object.hasOwnProperty(key))
当前回答
我会用另一个例子来解释。 假设我们有以下两个属性的对象:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
让我们创建TestObj实例:
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也会检查继承的属性,而hasOwnProperty则不是这样。
我会用另一个例子来解释。 假设我们有以下两个属性的对象:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
让我们创建TestObj实例:
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))
...产生同样的结果,答案是显而易见的,视情况而定。
你的回答非常棒。 我只是想提供一些东西,将节省你需要检查“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
}
}
这样做是为了避免迭代继承的属性。
如果你想创建一个简单的对象,它只会被用作“map”(即键值对),你可以这样做:
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
}
我在这里学到了这个很棒的技巧
总之,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
在这段代码中,hasOwnProperty()在传入“title”时返回true 因为title是一个对象实例;时,该方法返回false 传入" toString "是因为它在实例中不存在。当 每个属性名与in操作符一起使用,结果为真 两次都是因为它搜索实例和原型。
第一个版本更短(特别是在变量重命名的最小化代码中)
a in b
vs
b.hasOwnProperty(a)
不管怎样,正如@AndreMeinhold所说,它们并不总是产生相同的结果。