jclass

Advanced but lightweight and fast Javascript inheritance model providing class members and prototype conversion.

jclass

jclass started as a port of John Resig's lightweight OO inheritance model. However, this implementation is faster as it avoids threefold method wrapping (see here). In addition, it provides class members, property descriptors, conversion of prototype-based classes and various conveniences.

jclass has no dependencies and works in most import environments: RequireJS (AMD), CommonJS, NodeJs and web browsers.

Note: The current version (1.X.X) is a merge of the node-oo project and the previous version of jclass (0.2.X). For legacy code, see the v0.2.X branch.

jclass is hosted at npmjs. Install it via:

npm install jclass

All examples below use NodeJs but the jclass related code would also work in other environments.

var Class = require("jclass");
 
var Cat = Class._extend({
 
  // constructor 
  initfunction(color) {
    this.color = color;
  },
 
  // instance method 
  meowfunction() {
    console.log("An abstract cat cannot meow!");
  },
  
  // instance method 
  getColorfunction() {
    return this.color;
  }
 
});
 
 
var GrumpyCat = Cat._extend({
 
  // constructor 
  init: function init() {
    init._super.call(this, "greyish");
    
    // if you don't want to use a named function you can also use 
    // this.init._super.call(this, "greyish"); 
  },
 
  // instance method 
  meowfunction() {
    console.log("Nah, not in the mood.");
  }
 
});
 
var cat = new Cat("black");
cat.meow(); // "An abstract cat cannot meow!" 
 
var grumpy = new GrumpyCat();
grumpy.meow(); // "Nah, not in the mood." 
grumpy.getColor(); // "greyish", same as grumpy.color 
 
// instanceof works as expected 
console.log(grumpy instanceof GrumpyCat); // true 
console.log(grumpy instanceof Cat); // true 
console.log(GrumpyCat._extends(Cat)); // true, same as GrumpyCat._superClass == Cat 
console.log(GrumpyCat._extends(Class)); // true 

Class members are accessible via the _members property which is itself a jclass instance. To add class members, add a second paramter to _extend.

var Class = require("jclass");
 
var Cat = Class._extend({
  // instance members 
 
  // constructor 
  initfunction(color) {
    this.color = color;
  },
 
  // instance method 
  meowfunction() {
    console.log("An abstract cat cannot meow!");
  }
 
}, {
  // class members 
 
  family: "Felidae",
 
  getFamilyfunction() {
    console.log(this.family);
    // same as 
    // console.log(Cat._members.family); 
  }
 
});
 
Cat._members.getFamily()); // "Felidae", same as Cat._members.family 

Please note that this within class methods references the _members instance itself.

All instance and class members given to _extend can also be applied as property descriptors that are passed to Object.defineProperty. All you need to do is define members as objects and add a property descriptor: true. Both, accessor-type and data-type descriptors are supported.

var Class = require("jclass");
 
var MyClass = Class._extend({
 
  someKey: {
    descriptor: true,
    getfunction() {
      return "some value";
    }
  }
 
});
 
var myInstance = new MyClass();
console.log(myInstance.someKey); // "some value" 
 

You can convert prototype-base classes into jclasses. This approach supports constructor arguments.

// example using nodejs 
 
var Class        = require("jclass");
var EventEmitter = require("events").EventEmitter;
 
var Emitter = Class._convert(EventEmitter);
 
var emitter = new Emitter();
emitter.on("topic", function() { ... });
emitter.emit("topic", ...);
});

The instance of the (original) prototyped class is stored as _origin in each jclass instance.

Classes have the following attributes:

  • _extend (function(instanceMembers, classMembers)): Derives a new class with instanceMembers and classMembers (example).
  • _extends (function(Class)): Returns true (false) if Class is (is not) a super class.
  • _superClass (Class): The super class (not available for the base Class).
  • _subClasses (array): An array containing all (directly inheriting) sub classes.
  • _members (Class instance): A jclass instance that handles the class members (example).

The base Class has additional attributes that are not propagated to derived classes:

  • _convert (Function(cls, options)): Converts a prototype based class cls into a jclass (example).
  • _construct (Function(cls, args)): Returns an instance of cls, instantiated with args. This is an apply-like usage for new.

All instances have the following attributes:

  • _class (Class): The class of this instance

Within instance methods, the super method is always referenced as _super.

If the option exposeClassMembers is true, each instance can directly access class members within instance methods. You can use the _class attribute outside of instance methods or if exposeClassMembers is false.

Marcel R. (riga)