继承属性中使用的对象文字更改了类的所有实例

时间:2012-03-29 00:48:25

标签: javascript inheritance object-literal

我有以下代码(ObjA)并且它可以正常工作,实例'a1'具有与'a2'相同的属性但具有不同的值。

function ObjA() {
    this.objLiteral = {};
    this.propA = 0;
}

var a1 = new ObjA();
a1.objLiteral['hello'] = 3;
a1.propA = 1.5;

var a2 = new ObjA();
a2.objLiteral['goodbye'] = 4;
a2.propA = 2;

a1和a2的调试器信息:
http://www.flickr.com/photos/76617756@N02/6879283032/

接下来,我有以下从ObjA继承的ObjB。实例'b1'和'b2'具有相同的属性和属性propA和propB的不同值,但由于某种原因,objLiteral在两者中都是相同的,就像它引用相同的对象一样。

ObjB.prototype = new ObjA();
ObjB.prototype.constructor=ObjB;

function ObjB() {
    this.propB = 2;
}

var b1 = new ObjB();
b1.objLiteral['hello2'] = 6;
b1.propA = 4;
b1.propB = 5;

var b2 = new ObjB();
b2.objLiteral['goodbye2'] = 8;
b2.propA = 6;
b2.propB = 7;

b1和b2的调试器信息:
http://www.flickr.com/photos/76617756@N02/6879283088/

有人可以帮我理解发生了什么吗?我该怎么办才能满足我的期望? 非常感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

嗯,对象b1b2都有相同的原型,即ObjA的实例:

ObjB.prototype = new ObjA();

因此他们继承并访问其属性。 b1.objLiteralb2.objLiteral引用相同的对象:

enter image description here

> b1.objLiteral === b2.objLiteral
  true

要解决此问题,您必须为每个实例创建一个新对象。这通常是通过调用“child”构造函数中的“parent”构造函数来完成的:

function ObjB() {
    ObjA.call(this);
    this.propB = 2;
}

ObjA.call(this)将调用ObjA,在该函数中,this将引用传递给call [MDN]的参数,在本例中为ObjB的新实例:

enter image description here

如您所见,objLiteral现在是每个实例的属性:

> b1.objLiteral === b2.objLiteral
  false

为了避免这种混淆,应该避免将父构造函数的实例设置为子构造函数的原型。如果父构造函数需要特定于实例的参数怎么办?在这种情况下,你会传递给ObjA什么?

最好将子构造函数的原型设置为父构造函数的 prototype (具有一个间接级别),并像上面一样调用父构造函数:

function inherit(Child, Parent) {
    var Tmp = function() {};
    Tmp.prototype = Parent.prototype;
    Child.prototype = new Tmp();
    Child.prototype.constructor = Child;
}

inherit(ObjB, ObjA);
如果您稍后延长Tmp,则

Parent.prototype阻止延长Child.prototype


关于propA

它“有效”,因为你要为它分配一个新值。

在将属性分配给x.objLiteralx.propA之后,再次出现这些对象。您可以看到对象没有自己的objLiteral属性,而是自己的propA

enter image description here

相反,如果您将新值分配给objLiteral,例如通过

b1.objLiteral = {hello: 42};

b1现在将拥有自己的属性objLiteral,它会隐藏继承的属性:

enter image description here