如果(键入对象)或如果(object.hasOwnProperty(键)
以下两个语句是否产生相同的输出? 有没有什么理由更喜欢一种方式?
if (key in object) if (object.hasOwnProperty(key))
小心 – 他们不会产生相同的结果。
in
也会返回true
如果key
在原型链的某个地方被find,而Object.hasOwnProperty
(就像这个名字已经告诉我们的那样),只有在该对象可以直接使用key
(它的“拥有”属性)时才会返回true
。
我试着用另一个例子来解释。 假设我们有以下两个属性的对象:
function TestObj(){ this.name = 'Dragon'; } TestObj.prototype.gender = 'male';
让我们来创buildTestObj的实例:
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
也将检查inheritance的属性, hasOwnProperty
不是这种情况。
总之,hasOwnProperty()不会在原型中寻找原型。
采取的formsO'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是一个对象实例; 当传入“toString”时,该方法返回false,因为它不存在于实例中。 当每个属性名称与in运算符一起使用时,结果两次都是真实的,因为它search实例和原型。
另一种forms(称为in)枚举对象的属性名称(或键)。 在每次迭代中,对象的另一个属性名称string被分配给variables。 通常需要testingobject.hasOwnProperty(variables)来确定属性名称是否是对象的成员,或者是在原型链上find的。
for (myvar in obj) { if (obj.hasOwnProperty(myvar)) { ... } }
(来自Crockford的Javascript:The Good Parts )
你有一些非常好的答案。 我只是想提供一些东西,这将节省你迭代对象时检查“hasOwnProperty”的需要。
当创build一个对象时,通常人们会这样创build它:
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 } }
我们这样做是为了避免遍历inheritance的属性。
如果您打算创build一个仅用作“地图”(即键 – 值对)的简单对象,您可以这样做:
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 }
我在这里学到了这个真棒技巧
第一个版本更短(尤其是在variables被重命名的缩小代码中)
a in b
VS
b.hasOwnProperty(a)
无论如何,正如@AndreMeinhold所说的,他们并不总是产生同样的结果。