JavaScript将对象作为属性继承

JavaScript inherit object as property

本文关键字:属性继承 对象 JavaScript      更新时间:2023-09-26

我目前拥有的是一个对象,比如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"

http://jsfiddle.net/qqmtb846/

到目前为止,一切都很好。在对象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

http://jsfiddle.net/eb6dsgv9/1/

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

1) 这是JavaScript的某种设计弱点吗?2) 我该如何解决此问题?

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

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

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

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

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

var a = function () {
    this.value = {
        val: "value a"
    };
};

然后您可以从bc的构造函数调用该构造函数:

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);
};

http://jsfiddle.net/eb6dsgv9/6/

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

http://jsfiddle.net/eb6dsgv9/3/

var a = (function(){
    this.value = {
        val : "value a"
    }
});
var b = (function(){
    a.call(this);
    this.value.val = "b";
    alert("object b: " + this.value.val);
});
var c = (function(){
    a.call(this);
    alert("object c: " + this.value.val);
});
var ObjectB = new b();
var ObjectC = new c();

这里,"value"是"a"的属性,而不是a.prototype。在"a"answers"c"构造函数中,您可以创建新的、单独的"a",因此每次都会获得新的"value a"。它的缺点是,所有"a"实例都要花费更多的内存。

我的答案基于此:Javascript属性继承

Object.create(a.prototype)创建一个全新的对象,其[prototype]指向a.prototype。新的ObjectBObjectC是全新的对象,它们的[prototype]分别指向c.prototypeb.prototype您上面的[prototype]指向a.prototype的新空对象。

b constructor中,您尝试将属性value.val设置为"b",但ObjectB没有这样的属性value。javascript将再次查看b原型空对象,但在其CCD_ 24中具有到另一个对象CCD_ 25的链接。该对象具有属性CCD_ 26,因此它被设置为CCD_。

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

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