1

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

如果我错了,请纠正我,但除非这不使用经典继承,否则不会barFoo下面的代码中继承?当属性是继承属性时,为什么该hasOwnProperty方法返回 true ?propname我在这里做错了什么?

另外,我将如何hasOwnPropertyFoo对象上使用?此处的代码在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
4

5 回答 5

5

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

hasOwnPropertyfalse如果属性将返回:

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

代码中的“类”与继承无关,它只是一个在对象上设置一些属性的函数。

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

想象一下将函数重写为:

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

var baz = foo();

您希望baz.hasOwnProperty('propname')返回 true 吗?绝对可以,因为我们明确定义了对象的属性。

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

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

Foo.prototype.propname = 'test';

var baz = new Foo();

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

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

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

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

有一篇很好的文章解释了为什么new在 Javascript 中难以进行面向对象编程。

于 2015-04-12T09:08:56.810 回答
3

初始代码示例等效于:

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')返回 true(该属性已在 bar 对象上显式设置),并Foo.hasOwnProperty('propname')返回 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
于 2015-04-12T09:19:18.327 回答
2

不,propname实际上是在由创建的实例上设置的,基于(即)。构造函数模式的另一个近似值可以清楚地(呃)发生了什么:FoonewFoo.prototypethis

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";
于 2015-04-12T09:07:46.650 回答
1

当您第一次编写 Foo 时,您只是定义了一个稍后使用的函数。

“栏”实例化了该功能,并从本质上激活了其中的所有内容。

用这些 console.logs 看看这个小提琴

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

https://jsfiddle.net/7pzwcrjo/

于 2015-04-12T09:13:15.510 回答
1

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

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

如您所见,仅当您实例化类 Foo 的新对象时才调用构造函数,在这种情况下,该对象是一个名为 bar 的变量。您正在调用函数 Foo 的 hasOwnProperty。此函数不包含任何属性。

于 2015-04-12T09:14:28.470 回答