Objective-JavaScript for everyday use. Minimalistic but readable API. Perfect base for a clean / extendable design. A single file called eppz!js!class.min.js
is what you're looking for.
Creating classes, and instances are pretty straightforward.
// An imaginary View class.
var View = Class.extend
({
id: '',
div: null,
construct: function(id)
{
this.id = id;
this.build();
},
build: function()
{
this.div = document.createElement('div');
this.div.id = this.id;
},
});
var widget = new View('widget_1');
console.log(widget.id); // widget_1
Extend classes as well.
// An imaginary Widget class, subclass of View.
var Widget = View.extend
({
construct: function(number)
{
this.id = 'widget_'+number;
this.build();
},
});
var widget = new Widget(1);
console.log(widget.id); // widget_1
Better using superclass implementation for maintainability, safety and peace.
// With super calls.
var Widget = View.extend
({
construct: function(number)
{
this.super.construct('widget_'+number);
},
});
var widget = new Widget(1);
console.log(widget.id); // widget_1
Or using class methods for factories and more.
// Cool factory methods.
var Widget = View.extend
({
// No instance methods implemented.
},
{
widgetWithNumber: function(number)
{
return new this('widget_'+number);
}
});
var widget = Widget.widgetWithNumber(1);
console.log(widget.id); // widget_1
Many JavaScript class implementation does not take care of passing the correct this
reference (calling instance) for superclass method calls. With eppz!js Class your super
calls works as you'd expect.
var Widget = View.extend
({
color: 'Default',
getColorDescription: function()
{
return 'My color is '+this.color+'.';
}
});
var BlueWidget = Widget.extend
({
color: 'Blue',
getColorDescription: function()
{
return 'As you would expect. '+this.super.getColorDescription();
}
});
var widget = new BlueWidget();
console.log(widget.getColorDescription()); // As you would expect. My color is Blue.
There are class implementations out there that would output Default
as color here. Actually the main reason I made this Class
implementation was to get over this issue.
This method works over any amount of cascading super calls, as super references are bound right to the functions instead of the calling instance. Passing over the calling instance is done by a proxy object that wraps every superclass method into a function that does the job. See the implementation for further details if interested at all.
As soon as you define an Array
property, enumerators will be synthesized for you upon instance construction.
var Alphabet = Class.extend
({
letters: [],
logLetters: function()
{
this.enumerateLetters(function(eachLetter, eachIndex) // Created automagically.
{ console.log(eachIndex+': '+eachLetter); });
}
});
var alphabet = new Alphabet();
alphabet.letters = ['A','B','C','D'];
alphabet.logLetters();
// 0: A
// 1: B
// 2: C
// 3: D
If a property map is present, accessors will be synthesized upon construction to keep properties synced. Great way to bind model changes to UI.
var Controller = Class.extend
(
{
width: 20,
div: null,
construct: function()
{
this.div = document.createElement('div');
}
},
{},
{
'width' : [ 'div.style.width', '%px' ]
}
);
var controller = new Controller();
console.log(controller.div.style.width); // 20px
controller.width = 40;
console.log(controller.div.style.width); // 40px
As a side effect, every object is equiped with keypath tools.
controller.setValueForKeyPath('20px', 'div.style.width');
console.log(controller.getValueForKeyPath('div.style.width')); // 20px
If you define a className
property, runtime instance will be named after. Easier debug, also you can use instanceof
inspections.
var Widget = Class.extend
({
className: 'Widget',
});
var widget = new Widget();
var test = (widget instanceof Widget);
console.log(test); // true
Beside this Class
implementation this repository collects some tools for everyday JavaScript development, mainly for personal use. Can take a look at some Array
and Element
tools, though.
Licensed under the Open Source MIT license.