0

Let's take an example of a circle object. When I copy the properties of this object to RoundButton with my custom extend function, I thought RoundButton will get the reference of area method from circle object.

So if I change the definition of area method in circle it will also change the area property in RoundButton but in the console, it remains as it was before. I am really confused if I have not cloned the properties but copied them why it is behaving like that.

var circle  = {  
        area: function() {
            return Math.PI * this.radius * this.radius;
        }
    };

function extend(destination, source) {
    for( var k in source ){
        if(source.hasOwnProperty(k)) {
            destination[k] = source[k];
        }
    }
    return destination;
}

var RoundButton = function (radius) {
    this.radius = radius;
};

extend(RoundButton.prototype, circle);

console.log(RoundButton.prototype.area);

// ƒ () { return Math.PI * this.radius * this.radius;}

circle.area = function() {
    return Math.PI * this.radius * this.radius * this.radius;
}

console.log(RoundButton.prototype.area);

// ƒ () { return Math.PI * this.radius * this.radius;}
Dharmendra
  • 216
  • 1
  • 14

2 Answers2

3

When you reassign:

circle.area = function() {
    return Math.PI * this.radius * this.radius * this.radius;
}

...the previous area function object loses a reference. Any objects that still referenced circle.area will keep that same reference, but circle itself will now have a different reference, to the new function.

This is what happens with assignment and is standard behaviour in JavaScript.

In your example you could get your desired behaviour by not copying circle's properties to the RoundButton.prototype object (with extend), but to assign circle to that prototype. That way mutations of the circle object will directly affect the prototype (since they are the same object reference). So replace:

extend(RoundButton.prototype, circle);

with:

RoundButton.prototype = circle;

and it will work like you expected.

Again, with the original version, RoundButton.prototype does not get a reference to the circle object, but to its member values directly (so to the area function). Any mutation of the circle object through assignment of values to its own properties, will go unnoticed for that prototype object.

trincot
  • 317,000
  • 35
  • 244
  • 286
2

In javascript, objects (functions are objects) are assigned to variables through references, unlike the primitive values string, number, or boolean.

Lets say that the function assigned to circle.area is referred to by "X".

var circle  = {  
    area: function() { // "X"
        return Math.PI * this.radius * this.radius;
    }
};

Later on you go and assign this function to a difference variable.

var RoundButton = {
    area: circle.area // "X"
};

So RoundButton.area is also referring to our "X". Now if you do:

circle.area = new Function("return 1");

You will change the reference of circle.area, but RoundButton.area still is referring to that "X".

fingeron
  • 1,152
  • 1
  • 9
  • 20