【问题标题】:Why does hasOwnProperty not recognise functions on an object's prototype?为什么 hasOwnProperty 不能识别对象原型上的函数?
【发布时间】:2014-04-22 02:53:59
【问题描述】:

我知道 JavaScript 中的 hasOwnProperty 方法仅用于识别当前类型的属性,但这里的原型链中有一些东西让我感到困惑。

假设我定义了一个名为 Bob 的类型,并以两种不同的方式将两个子函数分配给我的 Bob 类型:

function Bob()
{
    this.name="Bob"; 
    this.sayGoodbye=function()
    {
        console.log("goodbye");   
    }
}

Bob.prototype.sayHello= function()
{
    console.log("hello");   
}

现在除了在sayGoodbye 的情况下可以访问闭包范围之外,在我看来,属于Bob 类的两个函数应该或多或少相等。但是,当我使用 hasOwnProperty 查找它们时,就 JavaScript 而言,它们并不相同:

var myBob = new Bob();
console.log( myBob.name ); // Bob, obviously 
console.log( myBob.hasOwnProperty("sayHello"));  // false
console.log( myBob.hasOwnProperty("sayGoodbye")); // true
console.log( "sayHello" in myBob ); // true

就范围而言,这里发生了什么?如果没有连接sayHello()sayGoodbye() 属性,我无法创建Bob 类型的实例,那么就hasOwnProperty 而言,为什么原型方法是二等公民呢? Bob.prototype 是一种以某种方式独立于 Bob 类型而存在的类型,Bob 从中继承了一切吗?

【问题讨论】:

  • hasOwnProperty 的存在只是为了检查对象本身的属性,它明确地不会沿着原型链向上走,因为这会破坏目的。
  • 我想要澄清的是为什么 hasOwnProperty 无法识别类型自己原型上的属性。
  • 属性访问与范围无关,完全不同。
  • @glenatron - 真正的答案是因为hasOwnProperty() 就是这样设计的。它只直接检查对象的属性,而不是原型链中的任何地方。我可以看到一个不同函数的基本原理,它告诉你属性是在对象上还是在它自己的原型中,但这不是 .hasOwnProperty() 的目的。你可以写一个这样的函数。
  • @glenatron — 第一步是认识到范围与属性访问无关。第一个与lexical environment 中的变量解析有关,另一个与对象及其[[Prototype]] 链上的property name 解析有关。

标签: javascript prototype hasownproperty


【解决方案1】:

我认为您在这里混淆了一些概念。让我们从MDN 中引用这段话:

Object 继承的每个对象都继承hasOwnProperty 方法。 这个方法可以用来判断一个对象是否有 将属性指定为该对象的直接属性;不像in 运算符,此方法不会检查对象的原型 链

这就是这里的关键。当你使用new 时,JavaScript 会为this 分配一个全新的对象并返回它,这就是实例。在构造函数中声明的任何属性都是自己的属性prototype 上声明的属性不是,因为它们与同一对象的其他实例共享。

prototype 也是Object,例如:

Bob.prototype.hasOwnProperty("sayHello"); //=> true

myBob.constructor.prototype.hasOwnProperty("sayHello"); //=> true

【讨论】:

  • 这是否意味着我可以实例化一个新的Bob.prototype,它可以访问Bob 类型的所有共享属性,但不能访问它的构造函数?假设我喝醉了,这似乎是个好主意。
  • 是的,你如何继承,NewObject.prototype = Object.create(Bob.prototype)
  • @glenatron - Bob.prototype 已作为对象存在。您不必实例化一个来阅读其中的内容。
  • @elclanrs 这不是如何进行继承,但很可能是我应该如何进行继承。通常我只会说James.prototype = new Bob()
  • 嗯,是的,这就是你在旧浏览器中的做法,但它在某种程度上有点 hacky... 检查 polyfill developer.mozilla.org/en-
【解决方案2】:

我了解 JavaScript 中的 hasOwnProperty 方法仅用于识别当前类型的属性

这是不正确的。 hasOwnProperty 标识对象的自己的属性,即对象本身的属性。它不考虑对象[[Prototype]] 链上的继承属性。

例如

var foo = {name: 'foo'};

// Check for an own property
foo.hasOwnProperty('name'); // true

对象 foo 也从 Object.prototype 继承了一个 toString 方法,但它不是“自己的”属性:

typeof foo.toString             // function
foo.hasOwnProperty('toString'); // false

【讨论】:

  • 我知道关于更长的继承链。我遇到的具体困惑是,有人通过foo.prototype.name 专门声明了一个属性,因此该属性仅存在于foo 类型上,并且它是子级。尽管 own 属性的定义解释了我出错的地方,但我认为如果所有唯一属于 foo 及其子项的属性都被视为 foo 的属性而不是仅属于 foo函数声明中的那些。
猜你喜欢
  • 2018-03-02
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多