hasOwnProperty何时使用,何时不需要?

6
建议始终使用hasOwnProperty,但在许多情况下这并非必需。例如,请考虑以下代码:
var object = JSON.parse(somejsontext);
for(var prop in object) {
   console.log(object[prop]);
}

根据 MOZ 的文档https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty,我们应该使用 hasOwnProperty 来避免迭代非可枚举属性,例如:

虽然在这种情况下 prop 是对象的一部分,并且由 for..in 明确定义,但是需要注意的是有些属性可能不可枚举。

var buz = {
  fog: 'stack'
};

for (var name in buz) {
  if (buz.hasOwnProperty(name)) {
    console.log('this is fog (' + name + ') for sure. Value: ' + buz[name]);
  }
  else {
    console.log(name); // toString or something else
  }
}

但是实际测试该代码时,永远不会进入else分支。

那么什么时候使用hasOwnProperty才有意义呢?

更新:考虑到所选择的答案,我们可以在以下情况下安全地避免使用hasOwnProperty: - Object js没有通过任何javascript库或我们的代码进行扩展 - Object是我们可以控制的简单代码


https://dev59.com/PGYr5IYBdhLWcg3wfaSc - Andreas
1个回答

7

当一个原型包含你的代码没有预料到的可枚举属性时,问题就出现了。例如,假设在你的示例之前运行了以下内容:

Object.prototype.foobar = "hello";

在这种情况下,迭代buz将包括可以枚举的foobar原型属性。这种hasOwnProperty模式允许您的代码区分对象直接存在的属性和从原型祖先继承的属性。
问题不是“枚举非可枚举属性”(根据定义,除非您明确地通过getOwnPropertyNames获取它们,否则不可能),而是枚举继承的属性。当使用可能向高级原型添加可枚举属性的库时,这是一个问题,就像我上面所演示的一样。
如果您想向原型添加属性而不导致该属性被枚举,可以使用Object.defineProperty创建一个非可枚举属性:
Object.defineProperty(Object.prototype, "foobar", {
    value: "hello",
    enumerable: false,
    writeable: true,
    configurable: true
});

这样的属性在 buz 上的 for..in 循环中是 不会 出现的(即使直接在 Object.prototype 上进行 for..in 循环也是不会出现的)。


是的,但是当你掌控代码时,这样做就没有意义了(希望库没有扩展基本对象的原型)。 - albanx
@albanx 许多库都会大量扩展原生对象,甚至可能扩展 Object.prototype - Teemu
但在Mozilla示例中,为什么它不会遍历toString方法。 - albanx
@albanx 因为 Object.prototype.toString 不可枚举;请注意 Object.getOwnPropertyDescriptor(Object.prototype, "toString") 返回一个描述符对象,其中 enumerable: false - apsillers
@albanx 编辑了关于不可枚举属性的更多内容。 - apsillers
所以,当我们确定对象没有被扩展时,我们应该明确地使用hasOwnProperty。 - albanx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接