JavaScript:为什么 Object.hasOwnProperty 方法会这样?

JavaScript: Why does the Object.hasOwnProperty method behave like this?

我的理解是 Object.hasOwnProperty 方法检查对象是否有自己的 属性 名称,即非继承的 属性。这意味着当 属性 a. 不存在或 b. 时,函数应该 return false如果是遗传的话。

如果我错了请纠正我,但是除非这不使用经典继承,否则下面的代码中 bar 不是从 Foo 继承的吗?当 propname 属性 是继承的 属性 时,为什么 hasOwnProperty 方法 return 为真?我在这里做错了什么?

此外,如何在 Foo 对象上使用 hasOwnProperty?这里的代码 returns false 在检查 Foo 对象时。

function Foo() {
    this.propname = 'test';
}

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false

不,propname实际上是在new创建的Foo实例上设置的,基于Foo.prototype(即 this)。构造函数模式的另一种近似可以清楚(呃)发生了什么:

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";

这里的绊脚石是 Javascript 使用原型继承。你所看到的实际上根本不是继承。

hasOwnProperty 将 return false 如果 属性:

  1. 不存在。
  2. 存在,但仅在原型链上。

代码中的 'class' 与继承完全无关,它只是一个在对象上设置某些属性的函数。

该对象恰好是一个新的空对象的实例,因为您使用 new 关键字调用该函数,这可能是混淆的来源。

想象一下将函数重写为:

function foo() {
  var bar = {};
  bar.propname = 'test';
  return bar;
}

var baz = foo();

你认为 baz.hasOwnProperty('propname') 到 return 是真的吗?绝对可以,因为我们在对象上明确定义了 属性。

另一种声明 属性 的方法是在 Foo 的原型上声明它。

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false

同样,这里发生的神奇事情都归功于 new 关键字。当您使用 new 调用函数时,该函数会将 this 的值赋给一个新对象,并将该对象的原型设置为与您正在调用的函数的原型相同。

也许最简单的解释方法是 bar 上有一个 hasOwnProperty 方法,但是如果你调用 bar.hasOwnProperty('hasOwnProperty') 它会 return false.

这是因为 hasOwnProperty 方法位于原型链的最顶端,在 Object.prototype 上。 Javascript 中的每个对象都从这里继承,这就是为什么每个对象都会有一个 hasOwnProperty 方法。

good article 为什么 new 使面向对象编程变得困难 Javascript。

当您第一次编写 Foo 时,您只是简单地定义了一个函数供以后使用。

"bar" 实例化该函数并实质上激活其中的所有内容。

看看这个 fiddle 和这些 console.logs

console.log(Foo)
console.log(bar)

https://jsfiddle.net/7pzwcrjo/

您首先必须实例化 Foo 的一个新对象 class。

这个 JS bin 进一步说明了这一点:http://jsbin.com/zaredowive/2/edit?js,console,output

如您所见,仅当您实例化 class Foo 的新对象时才会调用构造函数,在本例中是一个名为 bar 的变量。您在函数 Foo 上调用 hasOwnProperty。此函数不包含任何属性。

初始代码示例等同于:

function Foo() {
}

var bar = new Foo();
bar.propname = 'test';

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false

这就是为什么 bar.hasOwnProperty('propname') returns true(属性 已明确设置在 bar 对象上),而 Foo.hasOwnProperty('propname') returns false( 属性 根本没有在 Foo 上设置,无论是在 Foo 对象本身还是原型上。

hasOwnProperty检查通常是这样使用的:

function Foo() {
    this.propname = 'test';
}
Foo.prototype.inheritedprop = 'test';

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(bar.hasOwnProperty('inheritedprop')); // returns false