【发布时间】:2012-11-29 19:13:52
【问题描述】:
以下两个语句是否产生相同的输出?有什么理由比另一种更喜欢一种方式吗?
if (key in object)
if (object.hasOwnProperty(key))
【问题讨论】:
标签: javascript
以下两个语句是否产生相同的输出?有什么理由比另一种更喜欢一种方式吗?
if (key in object)
if (object.hasOwnProperty(key))
【问题讨论】:
标签: javascript
小心 - 它们不会产生相同的结果。
in 也将返回 true 如果key 在 原型链 的某处被发现,而 Object.hasOwnProperty(就像名字已经告诉我们的那样)只会返回 true如果 key 在该对象上直接可用(它“拥有”该属性)。
【讨论】:
in will also return true if key gets found somewhere in the prototype chain 到底是什么意思。你能写一个例子吗?谢谢。
({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))
...产生相同的结果,答案很明显,视情况而定。
【讨论】:
in 也会检查继承的属性,hasOwnProperty 则不是这样。
【讨论】:
总之,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 时 传入“toString”是因为它在实例上不存在。什么时候 每个属性名称都与 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
}
我学到了这个很棒的技巧here
【讨论】:
另一种形式(在里面调用)枚举属性名(或键) 的一个对象。在每次迭代中,另一个属性名称字符串来自 对象被分配给变量。 通常需要测试 object.hasOwnProperty(variable) 判断属性名是否 确实是对象的成员,或者是在原型链上找到的。
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(来自 Crockford 的 Javascript: The Good Parts)
【讨论】:
in 运算符与 for-in 语句不同。
in 是一个关键字。但是 OP 正在询问作为 in 运算符的具体用法。作为for-in 声明的一部分,您的回答涉及其他用法。
正如其他答案所示,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() 上使用此方法,因为它也适用于使用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 所说,它们并不总是产生相同的结果。
【讨论】: