JavaScript将对象作为属性继承

JavaScript将对象作为属性继承,javascript,inheritance,Javascript,Inheritance,我现在拥有的是一个对象,比如b,它继承了另一个对象,比如a。在对象a中,我有一个对象作为属性(值)。为了澄清问题: var a = (function(){}); a.prototype.value = { val : "value a" }; var b = (function(){ this.value.val = "b"; alert("object b: " + this.value.val); }); b.prototype = Object.create

我现在拥有的是一个对象,比如b,它继承了另一个对象,比如a。在对象a中,我有一个对象作为属性(值)。为了澄清问题:

var a = (function(){});

a.prototype.value = {
    val : "value a"
};

var b = (function(){
    this.value.val = "b";
    alert("object b: " + this.value.val);
});

b.prototype = Object.create(a.prototype);
b.prototype.constructor = a;

new b();  // alerts "object b: b"

到目前为止,一切顺利。在对象b中,我将“value”对象的“val”属性设置为另一个值。正如预期的那样,设置了该值(值现在为“b”)

当我创建另一个对象时,比如说c,我希望得到原始值(“值a”)

事实并非如此。我相信这是由于对象引用

var a = (function(){});

a.prototype.value = {
    val : "value a"
};

var b = (function(){
    this.value.val = "b";
    alert("object b: " + this.value.val);
});

var c = (function(){
    alert("object c: " + this.value.val);
});

b.prototype = Object.create(a.prototype);
b.prototype.constructor = a;

c.prototype = Object.create(a.prototype);
c.prototype.constructor = a;

var ObjectB = new b(); // alerts "object b: b"
var ObjectC = new c(); // alerts "object c: b", I want that "object b: value a" is displayed

我想在超类中使用对象作为属性,因为大多数值都是相同的,但有时它们必须更改。尽管是一个新实例,但仍然有一个引用

1) 这是JavaScript的某种设计缺陷吗?
2) 如何解决此问题?

这是预期的行为。在构造函数中,
this.value
引用与
a.prototype.value
相同的对象。您可以使用新值覆盖
this.value
(这将使
a.prototype
及其属性保持不变),但如果您修改
this.value.val
,您将修改
a.prototype.value
val
属性

我不知道你所说的“设计弱点”是什么意思,所以我无法回答(1)。这就是JavaScript原型继承的工作方式

至于如何解决这个问题,我认为你需要给我们展示一个更具体的例子,因为我不认为有一个简单的一刀切的解决方案。可以通过使用深度复制而不是Object.create来解决这个问题(不过,根据您如何进行深度复制,您可能会丢失原型上的任何方法,如果原型有)。简单地说,如果您需要修改原型属性的属性,您将遇到这样的情况

可能更好的解决方案是为每个实例提供一组单独的数据值。让您的所有实例共享同一组数据值会在您的情况中造成混乱

初始化
的构造函数中的属性:

var a = function () {
    this.value = {
        val: "value a"
    };
};
var b = function () {
    b.prototype.constructor.call(this);
    this.value.val = "b";
    console.log("object b: " + this.value.val);
};

var c = function () {
    c.prototype.constructor.call(this);
    console.log("object c: " + this.value.val);
};
然后您可以从
b
c
的构造函数调用该构造函数:

var a = function () {
    this.value = {
        val: "value a"
    };
};
var b = function () {
    b.prototype.constructor.call(this);
    this.value.val = "b";
    console.log("object b: " + this.value.val);
};

var c = function () {
    c.prototype.constructor.call(this);
    console.log("object c: " + this.value.val);
};

这是预期的行为。在构造函数中,
this.value
引用与
a.prototype.value
相同的对象。您可以使用新值覆盖
this.value
(这将使
a.prototype
及其属性保持不变),但如果您修改
this.value.val
,您将修改
a.prototype.value
val
属性

我不知道你所说的“设计弱点”是什么意思,所以我无法回答(1)。这就是JavaScript原型继承的工作方式

至于如何解决这个问题,我认为你需要给我们展示一个更具体的例子,因为我不认为有一个简单的一刀切的解决方案。可以通过使用深度复制而不是Object.create来解决这个问题(不过,根据您如何进行深度复制,您可能会丢失原型上的任何方法,如果原型有)。简单地说,如果您需要修改原型属性的属性,您将遇到这样的情况

可能更好的解决方案是为每个实例提供一组单独的数据值。让您的所有实例共享同一组数据值会在您的情况中造成混乱

初始化
的构造函数中的属性:

var a = function () {
    this.value = {
        val: "value a"
    };
};
var b = function () {
    b.prototype.constructor.call(this);
    this.value.val = "b";
    console.log("object b: " + this.value.val);
};

var c = function () {
    c.prototype.constructor.call(this);
    console.log("object c: " + this.value.val);
};
然后您可以从
b
c
的构造函数调用该构造函数:

var a = function () {
    this.value = {
        val: "value a"
    };
};
var b = function () {
    b.prototype.constructor.call(this);
    this.value.val = "b";
    console.log("object b: " + this.value.val);
};

var c = function () {
    c.prototype.constructor.call(this);
    console.log("object c: " + this.value.val);
};

要添加到JLRishe答案中,您可以通过以下方式进行操作:

这里,“value”是“a”的属性,而不是a。在“a”和“c”构造函数中,您创建了新的、单独的“a”,因此每次都会得到一个新的“值a”。它的缺点是,您需要为所有“a”实例花费更多内存


我的答案基于此:

要添加到JLRIS答案中,您可以通过以下方式进行操作:

这里,“value”是“a”的属性,而不是a。在“a”和“c”构造函数中,您创建了新的、单独的“a”,因此每次都会得到一个新的“值a”。它的缺点是,您需要为所有“a”实例花费更多内存

我的答案基于此:

对象。创建(a.prototype)
创建一个全新的对象,其
[prototype]
指向
a.prototype
。 新的
ObjectB
ObjectC
是全新的对象,它们的
[prototype]
分别指向
c.prototype
<代码>b.原型
哪个是 上面的新空对象带有
[prototype]
指向
a.prototype

b构造函数中
尝试将属性
value.val
设置为“b”,但ObjectB没有这样的属性
。javascript然后研究了b原型,它再次 空对象,但在它的
[prototype]
中有链接到另一个对象,即
a.prototype
。该对象具有属性
,因此将其设置为
value.val=“b”

对于ObjectC,链接是相同的,唯一的区别是您正在查找属性
。Javascript查找
[prototype]
链中的每个对象,直到找到
属性,该属性位于
a.prototype
对象中

这不是javascript的设计弱点,而是它的优点。javascript不是OOP语言。

对象。创建(a.prototype)
用它的
[prototype]
指向
a.prototype
创建一个全新的对象。 新的
ObjectB
ObjectC
是全新的对象,它们的
[prototype]
分别指向
c.prototype
<代码>b.原型
哪个是 上面的新空对象带有
[prototype]
指向
a.prototype

b构造函数中