0

I have some questions related to prototypes.

If we have created one object say Dog through the help of Person function constructor. Say Person has 2 properties on each instance member.

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

Now we have created 10 object from this like Pug, Bulldog, etc.

var Pug =new Dog('pug','white');
var Bulldog =new Dog('Bulldog','black');

Now suddenly we want to add one more property in Dog in such way that all object can access it. We can do it two ways:

  1. Adding it inside the function constructor this.leg : 4
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

or

  1. Adding it using
Dog.prototype.leg = 4;

Now my question is in each of these variants, the property will be added its prototype property means as prototype member not as an instance member? why?

If after creating an object we want to add some property and we want it to be added as instance member means own property how can I do it?

What I am getting in browser console:

Pug { name : 'pug',color :'white'}
_ proto_ : { leg :4 }

What I am expecting:

Pug { name : 'pug',color :'white',leg :4 }
_proto_ :Object
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • In the first option, you're not changing the prototype - if you change the constructor function, then you'd get your expected result, since this will mean any new instance created through the constructor has that property. If you want to change the *existing* members, then you have no choice to do that automatically - you can either re-create all of them or collect them all and change them in a loop. You can't automatically transfer a property from the prototype to each instance. – VLAZ Dec 16 '19 at 12:49

2 Answers2

0

When you're doing this Dog.prototype.leg = 4; you're actually modifying the prototype itself. However, future instantiated objects will inherit that new property as an instance property.

The existing instances in memory will continue with the pre-existing instance properties when they were instantiated.

var Dog = function (name,color){
    this.name =  name,
    this.color = color
};

console.log("Existing instances in memory");
let toy = new Dog("toy", "brown");
let tay = new Dog("tay", "grey");
console.log(toy, "\n", tay); // Existing instances in memory.

console.log("Future instance in memory.");
Dog.prototype.leg = 4;
let toe = new Dog("tay", "black");
console.log(toe); // Future instance in memory.
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ele
  • 33,468
  • 7
  • 37
  • 75
  • "*So the future objects will inherit that new property*" also, any *current* object, since the prototype chain is of live objects. – VLAZ Dec 16 '19 at 12:50
  • @VLAZ the prototype object yes, the instance (constructor properties) doesn't. – Ele Dec 16 '19 at 12:51
  • Your answer suggests that the *current objects* will not get a `leg` property after you modify the prototype but they *do*. There is no difference between "current" and "future" objects - in both cases they get a `leg` property and it always comes from the prototype, it's not an instance property on the actual `Dog` object. – VLAZ Dec 16 '19 at 12:53
  • The answer is still incorrect - the objects *do not get an instance property* - all Dog objects before and after the prototype change get the new prototype *from the prototype*. [Here is what happens with the old objects after changing the prototype](https://jsfiddle.net/u9ex0aks/1/). Neither the old ones nor the new ones will get a new instance property - it's always *the same one*. They all share the same property and if you do `toy.leg = 3`, then *all* dogs will be three legged. – VLAZ Dec 16 '19 at 13:41
  • Apologies, `toy.leg = 3` will assign an actual instance property, so the rest of the dogs will have `leg = 4`. Still, the prototype property is not an instance property. – VLAZ Dec 16 '19 at 13:50
  • in toe object leg not comes under instance property but it will come under prototype property the output { "name": "tay", "color": "black", "leg": 4 } is wrong actual one is { "name": "tay", "color": "black", } _proto_ : leg : 4 i would need output like you have posted while updating it later. But I am not getting – Gourab Banerjee Dec 18 '19 at 10:17
0

Using option 1 will attach an instance property on each new object created:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

Since it does, this means that you will get the exact output you expect. However, this will only be true for any new object instances created - the old ones will not be modified, as you can see above.

With option 2 all instances will get access to a leg property through their prototype regardless of when you've done the modificatin:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//modify prototype
Dog.prototype.leg = 4;

var Dalmatian = new Dog('dalmatian', 'spotted');

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

So, this will affect objects created before the change but if you want this to all be instance properties, then that's not going to happen - as you can see .hasOwnProperty('leg') returns false since they all access it through the prototype.

If you want to modify all Dog objects that were created before and after some change - the prototype chain is the easiest option. However, if you want to modify the instances, there is no easy way to do it. You can either recreate all objects:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//re-create
Pug = new Dog(Pug.name, Pug.color);
Bulldog = new Dog(Bulldog.name, Bulldog.color);

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

Or modify them:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//modify
Pug.leg = 4;
Bulldog.leg = 4;

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

In either case, you need to have a reference to all old objects.

One final thing to note with option 1 is that if you change the function, then you will create new Dog objects but they will not be the same Dog objects as before, since the function is now different:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

console.log("Bulldog is dog:", Bulldog instanceof Dog); //true - constructed with current Dog

//overwrite the constructor function - it's now *different*
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

console.log("Dalmatian is dog:", Dalmatian instanceof Dog); //true - constructed with  the new Dog

console.log("Bulldog is dog:", Bulldog instanceof Dog); //false - *not* constructed with the new Dog

If that difference matters, then you either need a different way of identifying the objects, or to recreate them. Alternatively, the prototype change will avoid the mismatched constructors but, again, you will not get the instance properties.

VLAZ
  • 26,331
  • 9
  • 49
  • 67