2015-04-12 29 views
1

我的理解是,Object.hasOwnProperty方法检查对象是否具有它自己的属性名称,即非继承属性。这意味着,只要属性a就应该返回false。 b。不存在b。如果它被继承,则为JavaScript:为什么Object.hasOwnProperty方法的行为如此?

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

另外,如何使用Foo对象上的hasOwnProperty?在检查Foo对象时,此处的代码返回false

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

var bar = new Foo(); 

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

的这条线2 ===栏上,没有原型属性这里设置。通过设置Foo.prototype.propname = ...添加原型。# – Douglas

+1

Bar是Foo的一个实例,而不是后代。 – joews

+0

@Douglas请你详细说明一下吗?为什么这需要原型呢?该方法正在检查属性... – shmuli

回答

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')真(物业已经栏对象上明确设置),并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 
+0

为什么没有在'Foo'上设置属性? – shmuli

+0

让我再说一遍:为什么当'this'关键字或'prototype'被使用时,为什么不是实际设置在'Foo'上的属性?在'Foo'上下文中,不应该使用'this'关键字来设置属性?为什么这不起作用:'function Foo(){Foo.propname ='test';}'。我想这完全是同一个问题。为什么只有当我在函数的外面写'Foo.propname ='test';'时才起作用? – shmuli

+0

示例中有三个不同的对象:bar,Foo和Foo.prototype。 hasOwnProperty方法检查属性的特定对象,因此如果仅在三个对象中的一个上设置了propname,那么只有该对象才会为'obj.hasOwnProperty(“propname”)'返回true。 '函数Foo(){Foo.propname ='test';}'将在Foo上设置propname,但只有当Foo被调用时它才会被设置。 – Douglas

2

没有,propname实际上是设置在实例Foonew创建,基于Foo.prototype(即this)。构造模式的另一个近似清楚(ER)是怎么回事:

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

的障碍在这里的一点是,JavaScript使用原型继承。你所看到的并不是真正的继承。如果物业

hasOwnProperty将返回false

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

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

该对象恰好是一个新的空对象的实例,因为您用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的值赋值为一个新对象,并将该对象的原型设置为与您要调用的函数的原型相同。

也许解释了这个问题最简单的办法是,有上bar一个hasOwnProperty方法,但是如果你调用bar.hasOwnProperty('hasOwnProperty')它将返回false

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

有一个good article为什么new在Javascript中使面向对象编程变得困难。

+0

这也许就是为什么Addy Osmani在“学习JavaScript设计模式”(http://addyosmani.com/resources/essentialjsdesignpatterns/book/#constructorpatternjavascript)中建议不要使用基本构造函数模式,而是使用原型模式?他说构造函数模式“使继承困难”,但没有进一步阐述。确切地说, – shmuli

+0

。与Doug Crock没有使用新的理由一样(尽管他不再使用Object.create)花费一些时间用另一种语言进行原型继承(我可以推荐Lua和Io),这对于理解原型很有帮助。在感觉古典的语法下,它们会略微丢失。 –

1

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

“酒吧”实例化该功能,实质上激活里面的一切。

看看这个捣鼓这些console.logs

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

https://jsfiddle.net/7pzwcrjo/

1

你首先必须初始化Foo类的新对象。

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

正如你可以看到当你实例化类Foo的一个新的对象,在这种情况下,是一个叫巴变量构造函数只调用。您正在调用函数Foo的hasOwnProperty。该功能不包含任何属性。

相关问题