views:

47

answers:

1

I use Resig's makeClass() approach for constructors:

// makeClass - By John Resig (MIT Licensed)
// Allows either new User() or User() to be employed for construction. 
function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      if ( typeof this.init == "function" )
          this.init.apply( this, (args && args.callee) ? args : arguments );
    } else
      return new arguments.callee( arguments );
  };
}

// usage:
// ------
// class implementer:
//   var MyType = makeClass();
//   MyType.prototype.init = function(a,b,c) {/* ... */};
// ------
// class user:
//   var instance = new MyType("cats", 17, "September");
//      -or-
//   var instance = MyType("cats", 17, "September");
//



var MyType = makeClass();

MyType.prototype.init = function(a,b,c) {
    say("MyType init: hello");
};

MyType.prototype.Method1 = function() {
    say("MyType.Method1: hello");
};

MyType.prototype.Subtype1 = makeClass();

MyType.prototype.Subtype1.prototype.init = function(name) {
    say("MyType.Subtype1.init:  (" + name + ")");
}

In that code, MyType() is a toplevel type, and MyType.Subtype1 is a nested type.

To use it, I can do:

var x = new MyType(); 
x.Method1();
var y = new x.Subtype1("y");

Can I get a reference to the instance of the parent type, within the init() for Subtype1() ? How?

+2  A: 

Nope, not unless you write a class implementation that tracks this "outer" class explicitly, Javascript won't be able to give this to you.

For example:

function Class(def) {
 var rv = function(args) {
  for(var key in def) {
   if(typeof def[key] == "function" && typeof def[key].__isClassDefinition == "boolean")
    def[key].prototype.outer = this;
   this[key] = def[key];
  }

  if(typeof this.init == "function")
   this.init.apply( this, (args && args.callee) ? args : arguments ); 
 };

 rv.prototype.outer = null;
 rv.__isClassDefinition = true;
 return rv;
}

var MyType = new Class({
 init: function(a) {
  say("MyType init: " + a);
  say(this.outer);
 },

 Method1: function() {
  say("MyType.Method1");
 },

 Subtype1: new Class({
  init: function(b) {
   say("Subtype1: " + b);
  },

  Method1: function() {
   say("Subtype1.Method1");
   this.outer.Method1();
  }
 })
});

var m = new MyType("test");
m.Method1();

var sub = new m.Subtype1("cheese");
sub.Method1();
Tyson
note that there are a million different ways to write a class implementation, this is just a simple 1-minute example
Tyson
Thank you, this worked perfectly.
Cheeso