if(键入对象)或if(object.hasOwnProperty(键)

时间:2012-11-29 19:13:53

标签: javascript

以下两个语句是否产生相同的输出?有没有理由偏向另一种方式?

 if (key in object)

 if (object.hasOwnProperty(key))

7 个答案:

答案 0 :(得分:170)

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

如果在{em>原型链的某处找到in

true也会返回key,而Object.hasOwnProperty(就像名字已经告诉我们的那样) ),如果true直接在该对象上可用(它“拥有”该属性),则仅返回key

答案 1 :(得分:59)

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

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

结论:

    如果对象可以直接或从原型中访问属性,则运算符中的
  • 始终返回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))

...产生相同的结果,答案很明显,这取决于。

答案 2 :(得分:26)

in还会检查继承的属性,hasOwnProperty不是这种情况。

答案 3 :(得分:22)

总而言之,hasOwnProperty()不会查看原型,而in会查看原型。

取自O'Reilly High Performance 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是一个对象实例;该方法在返回false时返回false   传入“toString”,因为它在实例上不存在。什么时候   每个属性名称与in运算符一起使用,结果为true   这两次都是因为它搜索了实例和原型。

答案 4 :(得分:5)

你有一些非常好的答案。 我只想提供一些能够在迭代对象时省去检查“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
}

我学到了这个很棒的提示here

答案 5 :(得分:2)

  

另一个表单(要求输入)枚举属性名称(或键)   一个对象。在每次迭代时,另一个属性名称字符串来自   对象被分配给变量。 通常需要进行测试   object.hasOwnProperty(变量)判断属性名称是否为   是真正的对象成员,或者被发现在原型链上。

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

(来自Crockford的 Javascript:The Good Parts

答案 6 :(得分:-4)

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

a in b

vs

b.hasOwnProperty(a)

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