JavaScript将对象作为属性继承

时间:2014-10-07 08:52:54

标签: javascript inheritance

我目前拥有的是一个对象,比如b,它继承了另一个对象,比如说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中,我设置了' val'价值的属性'反对另一个值。正如预期的那样,设定了价值(现在价值是' b')。

当我创建另一个对象时,让我们说c,我希望我得到原始值('值为')。

事实并非如此。我确定这是应该参考的对象。

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)我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

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

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

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

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

初始化a.prototype.value构造函数中的属性:

a

然后你可以从var a = function () { this.value = { val: "value a" }; }; b的构造函数中调用该构造函数:

c

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

答案 1 :(得分:2)

要添加到JLR她的答案,您可以这样工作:

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'和'c'构造函数中,您创建了新的,单独的'a',因此每次都会获得一个新的'值'。它的缺点是你为所有'a'实例花费了更多的记忆。

我的回答基于此: Javascript property inheritance

答案 2 :(得分:1)

Object.create(a.prototype)创建了一个全新的对象,其[prototype]指向a.prototype。 您的新ObjectBObjectC是全新的对象,其[prototype]指向c.prototype。这是b.prototype 上面的新空对象[prototype]指向a.prototype

b constructor中,您尝试将属性value.val设置为" b"但是ObjectB没有这样的属性value。 javascript比再看看b原型 空对象,但其[prototype]中的链接指向a.prototype的另一个对象。该对象具有属性value,因此设置为value.val = "b"

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

这不是javascript的设计弱点,实际上它是它的力量。 javascript不是OOP语言。