Say we do this:
function Bird(name, color){
this.name = name;
this.color = color;
}
Bird.prototype.numLegs = 2;
Bird.prototype.print = function(){
return "Hi, I'm "+this.name+", a "+this.color+" bird with "+this.numLegs+" legs!";
}
const bob = new Bird("Bob", "yellow");
console.log(bob.print() );
Now this.numLegs
is not currently defined in Bob. Bob has no legs of his own. If you did bob.hasOwnProperty("numLegs")
it will be false - Bob has no legs. But because he’s a Bird, he can access the numLegs
in his prototype chain. So even though he has no legs of his own, he can borrow them from Bird
.
But what if Bob had an accident, a run-in with a caiman? Well, the default no longer applies, so we can:
bob.numLegs = 1.2;
And with this, Bob no longer knows about the default value in Bird, he has his own legs. Doing this, we’ve increased the amount of data stored for Bob, as he no longer has that shared property - but he has the advantage of customization, and a little birdie peg-leg. If that caiman had taken the legs of millions of birds, in whole or in part, then all those Bird instances would take a little more space each. But many small space increases would accumulate to a BIG one. And a full caiman.
Suppose we later found that Bob had committed Medicare fraud, faked the leg thing - he had the proper birdie number of legs all along! His girlfriend thought the peg-leg was stylish, so Bob… Well he doesn’t need the custom leg value. We can still:
delete bob.numLegs;
And with that, he becomes a little smaller, a little less custom…but can now access that shared value from Bird again.