0

In the following code I instantiate an object and it inherits properties in two completely different ways.

function C(){
    this.k1 = "v1";
}
C.prototype.k2 = "v2";
var o = new C;

The first (k1) seems to attach to the instantiated object (o) as an 'own' property, the second (k2) does not attach to anything in the instantiated object but seems to just access it's value through the _ _ proto _ _ property (or [[prototype]]). In a way it seems like the first way is analogous to (in every computing) making a 'copy' of a file on your desktop whereas the second way is analogous to making an 'alias' of a file on your desktop, and of course, in this analogy I'm makin 'files' are analogous to 'properties'.

I'm wondering if this is the correct way of imagining what's taking place and if so what the benefits and drawbacks are to using one method over the other. I'm assuming that using the prototype property saves memory because it doesn't force the newly instantiated object (o) to have keys (k1) as an 'own' property, but maybe I'm wrong.

Why would anyone choose one method over another?

Allan Socks
  • 261
  • 2
  • 10
  • 1
    In one you re-do it for each instance, in the other all instances share the same one. The one you choose should be based on whether you want the value to be shared across all instances, or specific to each instance. – Kevin B Jul 08 '14 at 21:04
  • thank you for your help, but is there any benefit? I can over write proto properties with 'own' properties. And I can overwrite properties that have been 're-done'. Although they are different they seem to basically do the same thing from where I'm standing. – Allan Socks Jul 08 '14 at 21:05
  • If you updated the property directly on an instance it would still only affect that instance, however, if you updated it on the prototype it would affect all instances where it hasn't yet been updated on the instance. See here: http://jsfiddle.net/4W2Nm/ – Kevin B Jul 08 '14 at 21:08
  • This might be of interest for you: [Should I put default values of attributes on the prototype to save space?](http://codereview.stackexchange.com/q/28344/25332) – t.niese Jul 08 '14 at 21:08
  • 2
    Typically you would never store something that may change on the prototype unless it's something that needs to be shared across all instances, however even then it's usually better to do something else, such as the revealing pattern. – Kevin B Jul 08 '14 at 21:11
  • Thank you Kevin, I see how they behave differently, but it seems like they behave differently like opening a door left handed and opening a door right handed behave differently. I could just find the constructor in my code and update all instances as easily as I could if I wrote over the prototype else in my code. It seems kind of like yes they are different but this difference is essentially not very meaningful. Maybe I'm wrong though, I'm a newbie. – Allan Socks Jul 08 '14 at 21:12
  • but... it's extremely meaningful. It does make a big difference. In one case you may have a constructor with a prototype with 5 functions and 50 instances, resulting in 5(6) functions, where as in the other you'll have 250(251) functions (5 for each instance) – Kevin B Jul 08 '14 at 21:13
  • Thank you, actually now it makes sense Kevin. – Allan Socks Jul 08 '14 at 21:14
  • I still don't see why it would make a difference if there were 250,000 functions, if you can just change all of them by just going to the constructor and changing the this keywords value in the constructor and then going to file->save all 250,000 would be updated. Likewise, if I were to overwrite the prototype itself it would change it for all 250,000 instances. I could also change each individual property in either case as well, hence my curiosity. The only two things I can think of that would be of benefit would be that it might save memory or that it's just housekeeping. – Allan Socks Jul 08 '14 at 21:19
  • I think memory and housekeeping are important and that makes sense but I don't see anything I can't do with one that I can do with the other. – Allan Socks Jul 08 '14 at 21:20
  • 1
    @AllanSocks there isn't anything you can do with one and not the other. That's not what the difference is about. You can accomplish everything you want without even touching the prototype. It just may not be as efficient, or maybe it'l be more efficient, depending on how you do it. – Kevin B Jul 08 '14 at 21:27

2 Answers2

2

I'm wondering if this is the correct way of imagining what's taking place

Yes.

Why would anyone choose one method over another?

.prototype

This is especially beneficial for methods (with their dynamic this binding)

this

  • values are specific to each instance
  • methods defined there are closure which have access to the constructor scope and therefore allows true privacy.

The own properties are necessary for the data that distinguishes the instances.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

Think of the prototype as what is inherited. In a classic OOP world, it's almost like a parent class.

The advantage of using a prototype is that for instances of C which do not customize k2, there will be only a single value stored in memory. If you set the property on an instance, however, you create a new property that is within the object directly (hasOwnProperty will return true).

The disadvantage is that it may not be clear to all who read your code how that value gets set.

Also, keep in mind, if a default does not make sense, and you always need to compute it, then putting it in the prototype makes little sense.

FYI, this is why you will often see methods bound to an object via its prototype, since they just define code and are generally stateless by themselves.

function C() {
  this.blah = function () {
    return 1;
  };
  // other stuff
}

var a = new C();
var b = new C();

You have 2 functions named blah in memory, not 1.

Versus:

function C() {
  // other stuff
}
C.prototype.blah = function () {
  return 1;
};

var a = new C();
var b = new C();

Now you only have a single blah function in memory, bound to 2 separate objects.

Brandon
  • 9,822
  • 3
  • 27
  • 37