UNMAINTAINED / DEPRECATED
I no longer use class helpers. I would encourage using ES6 classes if you feel the need to emulate classical OO patterns.
klasse
A minimal class/mixin utility for JavaScript (ES5+), focusing on performance, node compatibility, and composition over inheritance.
install
This tool is best used with NodeJS. You can install it like so:
npm install klasse
syntax
Inspired by MooTools and jsOOP, the syntax is simple and readable:
var Class = ; var MyClass = //Optional base class to extend from Extends: BaseClass //Optional array of mixins Mixins: myMixins initialize: { thisprop = "foo"; };
Keywords:
Extends
: Optional. Specifies the base class for prototype chain.Mixins
: Optional. Can be an array of mixins, or just a single mixin. A mixin is an object or Class which defines methods, properties, and so forth to be added directly to a class prototype.initialize
: Optional. The constructor method, generally a named function for clearer debugging. If not specified, and a base class is given toExtends
, the constructor will default to calling the base class constructor. Otherwise, an empty constructor will be used.
performance & V8 optimizations in mind
Encourages best performance in a number of ways:
- Lookups in a long prototype chain can be more costly, so composition over inheritance is encouraged with Mixins.
- No funky magic going on in the constructor (like in MooTools) -- just what you've defined for
initialize
. This is more ideal for V8 optimizations (hidden classes). - Does not clutter objects with caller/super/etc. information. Too many properties in a class will make it less likely to be optimized by V8 and other engines.1
constructor best practices
- Use a named constructor function so it appears correctly in the debugger, and in stack traces. This is optional, but leads to clearer debugging.
- Declare all instance variables for the class up-front in the constructor. This is done for two reasons:
- It's ideal for hidden classes in V8 and other engines.
- If you declare an instance property on the object passed to the
Class
constructor, it will be placed in the object's prototype. This leads to an unnecessary lookup in the prototype chain. It also may cause problems for Arrays and Objects, because they are not re-initialized as you might expect.
example
Here is a Vector example, where we reduce duplicate code but favour composition rather than inheritance. Inheritance (i.e. Vector3 extends Vector2) would lead to unnecessary lookups on the prototype chain.
var Class = ; //A lightweight mixin which contains functions, properties, etc //to be placed on the prototype.var mixins = { return Math; }; var Vector2 = //Mixin the length. This accepts an array of mixins //(lightweight objects, or a new Class) or you can //just specify a single mixin. Mixins: mixins //We use named functions for the constructor, which //leads to nicer console logs on Chrome. initialize: { thisx = x || 0; thisy = y || 0; } { var x = thisx y = thisy; return x * x + y * y ; }; var Vector3 = Mixins: mixins initialize: { //We can call the constructor like so Vector2; thisz = z || 0; } { var x = thisx y = thisy z = thisz; return x * x + y * y + z + z; };
"simplified" properties
If an object in the class definition or a mixin has get
and/or set
functions, then we assume its a property. It looks like this:
var Person = initialize: { this_age = age || 0; } /** The 'age' property. */ age: { return this_age; } { if value < 0 throw "age must be positive"; this_age = value; } ; var p = 12;page += 2; //increases ageconsole; //prints 14page = -1; //throws error
Simplified properties are enumerable
and configurable
by default, unless otherwise specified. See below.
final properties
A property which has configurable
set to false will be considered final. Trying to Extend or Mixin and override such a property will throw an error. You can skip these errors by setting the Class.ignoreFinals
flag to true
before creating new classes. Then, only the first instance of that property will be included in your new Class.
Non-Node environments
You can grab the UMD file from the build
package, which is namespaced to klasse
. So your code might look like this:
var MyClass = new klasse.Class({
...
});
building
To build, install the necessary command-line tools:
npm install uglify-js yuidocjs browserify -g
Then run the build script from the project directory:
npm run build
License
BSD-2-Clause