以下两个语句是否产生相同的输出?有什么理由比另一种更喜欢一种方式吗?
if (key in object)
if (object.hasOwnProperty(key))
Answers:
小心-它们不会产生相同的结果。
in
true
如果key
在原型链中某处被找到,也会返回;而Object.hasOwnProperty
(就像名称已经告诉我们的那样),只会返回true
如果key
直接在该对象上可用(它“拥有”该属性)。
({foo:"bar"}).hasOwnProperty("toString")
vs"toString" in ({foo:"bar"})
我尝试用另一个例子来解释。假设我们有以下具有两个属性的对象:
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()
不看原型而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运算符一起使用时,两次结果均为true,因为它会搜索实例和原型。
您得到了一些非常好的答案。我只想提供一些东西,可以省去迭代对象时检查“ 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)
in
运营商比不同的for-in
说法。
in
是一个关键字。但是OP正在询问in
操作员的具体用法。您的答案是for-in
语句中其他用法的一部分。
第一个版本较短(尤其是在最小化代码中将变量重命名的版本)
a in b
与
b.hasOwnProperty(a)
无论如何,正如@AndreMeinhold所说,它们并不总是产生相同的结果。
in will also return true if key gets found somewhere in the prototype chain
?你可以写一个例子吗?谢谢。