enchant.js Class の仕組み

http://tatenosystem.com/download/JsClass.js.txt

/**
 * Create a class. from enchant.js
 */

var JsClass = function() {};

JsClass.create = function(superclass, definition) {
   if (superclass == null && definition) {
       throw new Error("superclass is undefined (JsClass.create)");
   } else if (superclass == null) {
       throw new Error("definition is undefined (JsClass.create)");
   }

   if (arguments.length === 0) {
       return JsClass.create(Object, definition);
   } else if (arguments.length === 1 && typeof arguments[0] !== 'function') {
       return JsClass.create(Object, arguments[0]);
   }

   for (var prop in definition) {
       if (definition.hasOwnProperty(prop)) {
           if (typeof definition[prop] === 'object' && definition[prop] !== null && Object.getPrototypeOf(definition[prop]) === Object.prototype) {
               if (!('enumerable' in definition[prop])) {
                   definition[prop].enumerable = true;
               }
           } else {
               definition[prop] = { value: definition[prop], enumerable: true, writable: true };
           }
       }
   }
   var Constructor = function() {
       if (this instanceof Constructor) {
           Constructor.prototype.initialize.apply(this, arguments);
       } else {
           return new Constructor();
       }
   };
   Constructor.prototype = Object.create(superclass.prototype, definition);
   Constructor.prototype.constructor = Constructor;
   if (Constructor.prototype.initialize == null) {
       Constructor.prototype.initialize = function() {
           superclass.apply(this, arguments);
       };
   }
 
   var tree = this.getInheritanceTree(superclass);
   for (var i = 0, l = tree.length; i < l; i++) {
       if (typeof tree[i]._inherited === 'function') {
           tree[i]._inherited(Constructor);
           break;
       }
   }
   
   return Constructor;
};

/**
 * Get the inheritance tree of this class.
 * @param {Function}
 * @return {Function[]}
 */
JsClass.getInheritanceTree = function(Constructor) {
   var ret = [];
   var C = Constructor;
   var proto = C.prototype;
   while (C !== Object) {
       ret.push(C);
       proto = Object.getPrototypeOf(proto);
       C = proto.constructor;
   }
   return ret;
};

// TEST

var Hoge = JsClass.create({
   echo: function() {
       console.log('hoge');
   }
});

var Fuga = JsClass.create(Hoge, {
   initialize: function() {
       console.log('init call');
   }
});

var f = new Fuga();
f.echo();