Wednesday, February 2, 2011

Prototypes, not your everyday inheritance

So a concern came up today around Javascript. Specifically it was that there are no private members in the language. I quickly spoke up saying that how closures work and the use of the var keyword keep your variables private but was met immediately with those are not instance variables and you can't have private instance members. It turns out there was some confusion as to what the prototype attribute does on functions and it's role with inheritance.

This was the example to prove that there are no private instance members in Javascript:

function Person() {
  //public member
  this.Name = "Copenhaver";

  //convention based "private"
  this._ccn = "5555555555555";

  /* thought this was unusable, but it's actually scoped inside
   * this invocation of the function and usable by other members of
   * the object currently being built.
  var ssn = "xxxxxxxxx";
}

/* this is actually creating a completely separate object that
 * will act as the parent of all objects built using Person()
Person.prototype = {
  getSSN: function(){
    //this doesn't do what you want
    //actually would try to grab this out of global scope
    return ssn;
  },

  getCCN: function(){
    //anyone could access this variable
    return this._ccn;
  }
};

Now the developer was used to using the prototype variable basically for class style definition and inheritance with Javascript. The confusion comes in with that as well. That prototype attribute on the function is going to point to a single object and that object gets hooked in as the parent of any object created with the function. Yeah think about that, so that would be a single object as the parent to many children. Not a class, an object. That is prototypical inheritance. If you wanted them disjointed then you would clone the parent first.

I personally see the prototype attribute as a bit of a wart on the Javascript language that just confuses the people who come in trying to use it the same as they did classes and inheritance in other languages. Anyway I'm starting to see all this constructor inheritance business in Javascript to be a bit off. I'm thinking that you should really think about these functions as initializers and inheritance as something to create off of:

var linkedChild1 = Object.create(sharedParent);
var linkedChild2 = Object.create(sharedParent);

//now you become a Panda... but it could effect everyone else making them sad
linkedChild1 = Panda(linkedChild1);

var unlinked1 = Object.create(parent.clone());
var unlinked2 = Object.create(parent.clone());

//now you become a Grizzly leaving everyone else behind so you can eat them
var raaar = Grizzly(unlinked1);

I haven't used this idea yet and it's partially based on a Crockford's Object.create() idea which is getting incorporated into Javascript. Figured, throw the idea out there and see what comes of it.

Links:
http://javascript.crockford.com/prototypal.html
http://javascript.crockford.com/private.html

No comments:

Post a Comment