Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript and function prototype assignment

I've always assumed that the prototype of a function was shared among all the objects, in a sense by reference. So if you change the value of a property of the prototype, all objects that share that prototype have the values change for them as well. So for instance below it seems that instead of the property bar being shared between all objects, it is copied. Is this right? Are the properties of the prototype of the constructor simply copied to all the class objects as they are created, or are they shared by linkage?

function foo()
{
     this.bar = 1;
}
function derived() { }
derived.prototype = new foo()

object1 = new derived()
object2 = new derived()

object1.bar = 2;
//but notice if I had said here derived.prototype.bar = 3, object1.bar would still equal 2 but object2.bar would equal 3
alert(object2.bar) // this prints 1;
like image 796
rubixibuc Avatar asked Oct 03 '11 05:10

rubixibuc


2 Answers

When you assign object1.bar = 2, you are creating an own property on object1, this property exist only in that object instance, and it has nothing to do with its prototype.

This property on object1 will shadow the value of the one existing on derived.prototype, this means that when you lookup object1.bar, it will find a value directly existing on that object.

On the other side, if you lookup object2.bar, this object doesn't have an own bar property, so the property lookup will search on the object this one inherits from (derived.prototype) and it will find the value 1.

Your object structure looks something like this:

 object1
 --------
| bar: 2 | -----------------
 --------                   |         derived.prototype
                            |        ----------
                            |------> | bar: 1  | --    foo.prototype
 object2 (no own properties)|        ----------   |   ------------------
 --------                   |                     -> | constructor: foo |
|        | -----------------                          ------------------
 --------                                                    |
                                                             v
                                                     ------------------
                                                    | Object.prototype |
                                                     ------------------
                                                             |
                                                             v
                                                            null

Where the ---> lines denote the internal [[Prototype]] link that expresses inheritance.

like image 68
Christian C. Salvadó Avatar answered Oct 19 '22 07:10

Christian C. Salvadó


For example, you have code:

function Animal() {
}
Animal.prototype.name="animal";

function Dog() {
}
Dog.prototype = new Animal
Dog.prototype.constructor=Dog;
Dog.prototype.name="dog";

object1 = new Animal();
object2 = new Dog();

As a result you have two object instances, that looked as (you can check this for example in Chrome devtools or FF firebug or...):

object1:
  __proto__: (is ref into an Animal.prototype object)
    constructor: function Animal()
    name: "animal"
    __proto__: Object (is ref into an Object.prototype object)

object2:
  __proto__: (is ref into an Dog.prototype object)
    constructor: function Dog()
    name: "dog"
    __proto__: (is ref into an Animal.prototype object)
      constructor: function Animal()
      name: "animal"
      __proto__: (is ref into an Object.prototype object)

When you run next code (for example):

alert(object1.name); // displayed "animal"
alert(object2.name); // displayed "dog"

What happened? 1) Javascript looked for property name in object instance (in object1 or object2). 2) When not found, it looked up in object instance proto property (that is same as prototype of class function). 3) When not founct it looked in proto of proto and next and next while not found name property and others proto found. If as result of search property is found, then value is returned, if not found, then undefined returned.

What happened if you execute next code:

object2.name = "doggy";

As a result you have for object2:

object2:
  name: "doggy"
  __proto__: (is ref into an Dog.prototype object)
    constructor: function Dog()
    name: "dog"
    __proto__: (is ref into an Animal.prototype object)
      constructor: function Animal()
      name: "animal"
      __proto__: (is ref into an Object.prototype object)

Property is assigned directly into instance object, but prototype object remains unchanged. And when you execute:

alert(object1.name); // displayed "animal"
alert(object2.name); // displayed "doggy"

When you need to create|change shared property of class, you can use one from next algoritms: 1)

Animal.prototype.secondName="aaa";
alert(object1.secondName); // displayed "aaa"
alert(object2.secondName); // displayed "aaa"
Animal.prototype.secondName="bbb";
alert(object1.secondName); // displayed "bbb"
alert(object2.secondName); // displayed "bbb"
// but
Animal.prototype.secondName="ccc";
object1.secondName="ddd";
alert(object1.secondName); // displayed "ccc"
alert(object2.secondName); // displayed "ddd"

2) Create property of type object in prototype of function class and assign values to properties of this object.

Animal.prototype.propObject={thirdName:"zzz"};
alert(object1.propObject.thirdName); // displayed "zzz"
alert(object2.propObject.thirdName); // displayed "zzz"
Animal.prototype.propObject.thirdName="yyy";
alert(object1.propObject.thirdName); // displayed "yyy"
alert(object2.propObject.thirdName); // displayed "yyy"
object1.propObject.thirdName="xxx";
alert(object1.propObject.thirdName); // displayed "xxx"
alert(object2.propObject.thirdName); // displayed "xxx"
object2.propObject.thirdName="www";
alert(object1.propObject.thirdName); // displayed "www"
alert(object2.propObject.thirdName); // displayed "www"
like image 24
Andrew D. Avatar answered Oct 19 '22 07:10

Andrew D.