2012-08-01 97 views
1

我一直在学习JavaScript的原型继承,我有一个标签在HTML页面的主体如下:Javascript对象构造 - 奇怪的行为

function F() {} 
//F.prototype = {a:"hello"}; 
var x = new F(); 
document.write(x.constructor); 

这将导致以下的打印输出浏览器:

函数F(){}

然而,如果我去掉第二条线,结果如下:

函数对象(){[本地代码]}

然而,x仍从F的原型,继承自当我最后一行更改为以下...

document.write(x.a); 

...我碰到下面的打印输出:

你好

我已经在Firefox和Safari中尝试了这一点,并且两者都发生同样的事情。

有没有人知道这里到底发生了什么?

+0

为何如此奇怪的呢?看起来像正常的JavaScript给我。 – kevin628 2012-08-01 15:09:37

回答

1

每个对象在其原型链中都有constructor属性,因为每个对象最终都从Object.prototype继承。

既然你设置一个普通的对象作为F原型,x.constructor现在指的是物体,这是指Object.prototype.constructorconstructor财产。

的原型链是这样的:

x -> F.prototype -> Object.prototype 

,并因为无论x也不F.prototypeconstructor属性,则返回Object.prototype.constructor值。

F.prototype的价值,你重写它之前是一样的东西:

F.prototype = { 
    constructor: F; 
}; 

即它有一个constructor属性。这就是为什么你应该总是设置constructor正确如果重写原型:

F.prototype = {a:"hello"}; 
F.prototype.constructor = F; 
+0

因此,x继承了来自'{a:“hello”}'的'constructor'属性,就像它继承了'a'属性一样?那么这是否意味着'x.constructor.prototype'对于遍历继承树是绝对没有用的? – user924731 2012-08-01 15:13:33

+0

@ user924731:我不太清楚你的意思,但也许我的编辑澄清了事情。如果你重写原型,确保你正确设置了'constructor'函数。 – 2012-08-01 15:17:21

0

那是因为你已经消除默认.constructor属性,当你取代了原来的.prototype对象。

所以,现在,当你看到一个.constructor财产继续下跌给定.prototype对象的原型链,直到它找到一个,它会从默认Object.prototype得到。

.prototype对象已经被替换,有些人喜欢重新分配丢失.constructor ...

function F() {} 
F.prototype = {a:"hello"}; 
F.prototype.constructor = F; 
+0

好的。我读过的东西表明你遍历了一个对象的继承树,使用'x.constructor.prototype'来遍历'x',所以我认为'constructor'属性不会被覆盖。 – user924731 2012-08-01 15:57:17

+0

@ user924731:是的,'.constructor'属性是一个默认属性,直接在默认的'F.prototype'对象上为您提供。如果你销毁了默认的'F.prototype'对象,你也失去了它的任何属性。这就是为什么它需要手动添加。 – 2012-08-01 16:10:19

+0

谢谢。我会喜欢,但我没有足够的声誉。 – user924731 2012-08-01 16:43:23