0

What I currently have is an object, say b, that inherits an other object, say a. In object a I have an object as property(value). To clear things up:

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/

So far, so good. In object b I set the 'val' property of the 'value' object to another value. As expected the value is set(value is now 'b').

When I create another object, lets say c, I would expect that I get the original value('value a').

This is not the case. I'm sure this is due object reference.

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/

I want to use an object as property in the super class because most of the values will be the same, but sometimes they have to change. There is still a referance despite it's a new instance.

1) Is this some kind of design weakness of JavaScript? 2) How can I resolve this?

3 Answers 3

2

This is expected behavior. In your constructor, this.value refers to the same object as a.prototype.value. You can overwrite this.value with a new value (which will leave a.prototype and its properties unchanged), but if you modify this.value.val you are modifying the val property of a.prototype.value.

I don't know what you mean by "design weakness" so I can't answer (1). This is simply the way JavaScript's prototypal inheritance works.

As for how to resolve it, I think you need to show us a more concrete example, as I don't think there's a simple one-size-fits-all solution to this. It could be resolved by using a deep copy instead of Object.create (though depending on how you do the deep copy you could lose any methods on the prototype, if it has any). To put it simply, if you need to modify the properties of the prototype's properties, you are going to run into a situation like this.

Probably a better solution is to have a separate set of data values for each instance. Having all your instances share the same set of data values is creating a mess in your situation.

Initialize the properties in a's constructor:

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

And then you can call that constructor from b and c's constructor:

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/

Sign up to request clarification or add additional context in comments.

Comments

2

To add to JLRishe answer, you can make it work this way:

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

Here, 'value' is property of 'a', not a.prototype. In 'a' and 'c' constructors you create new, separate 'a', so you get a fresh 'value a' each time. The downside of it is you spend more memory for all 'a' instances.

I based my answer on this: Javascript property inheritance

Comments

1

Object.create(a.prototype) creates a brand new object with it's [prototype] pointing to a.prototype. Your new ObjectB and ObjectC are brand new objects with their [prototype] pointing to c.prototype resp. b.prototype which is your above new empty object with [prototype] pointing to a.prototype.

In your b constructor you try set the property value.val to "b" but ObjectB does not have such a property value. javascript than looks into b prototype which is again empty object but has the link in it's [prototype] to another object which is a.prototype. that object has property value so it is set value.val = "b" .

In case of ObjectC the linking is the same, the only difference is that you are looking for property value. Javascript looks in every objects in the [prototype] chain until it finds the value property which is in your a.prototype object.

It is not design weakness of javascript it is it's strength actually. javascript is not OOP language.

5 Comments

JavaScript is an OOP language. It simply doesn't use class-based inheritance.
we can discuss that for hours. IMO delegation is not inheritance. It can be simulated though but it is not the same as OOP in Java.
Delegation vs. inheritance has nothing to do with whether a language is object oriented or not. JavaScript is an object oriented language. That's uncontroversial. It uses objects everywhere. From Wikipedia: "Object-oriented programming (OOP) is a programming paradigm that represents the concept of 'objects' that have data fields (attributes that describe the object) and associated procedures known as methods. C++, Objective-C, Smalltalk, Delphi, Java, Javascript, C#, Perl, Python, Ruby and PHP are examples of object-oriented programming languages."
my point is that fields are not inherited but delegated thus your object is not really an object the same way as understood in java. If you mention "associated procedures as methods" that does have some fundamentally different principles as well in contrast to the rest of the line.
Thank you for your answer. I definitely have to read more about prototype chain inheritance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.