Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple, but effective JavaScript class system
describe("class system", function(){
it("should be possible to create classes", function(){
Class({name:'MyClass'});
expect(window.MyClass === undefined).toBeFalsy();
});
it("should be possible to create properties within classes", function(){
Class({
name:'MyClass',
attrs:{
attr: 'myattr'
}
});
var instance = new MyClass;
expect(instance.attr).toBe('myattr');
});
it("constructor property should be overwritten", function(){
Class({
name:'MyClass',
attrs:{
attr: 'myattr'
}
});
expect(MyClass.prototype.constructor).toNotBe(Object);
});
it("should make the created class create instances even without the new keyword", function(){
Class({
name:'MyClass',
});
var m = MyClass();
expect(m instanceof MyClass).toBe(true);
});
it("should support namespaced classes", function(){
var Namespace = {};
Class({namespace: Namespace, name:'MyClass'});
expect(Namespace.MyClass === undefined).toBe(false);
});
it("should support inheritance", function(){
Class({
name:'ParentClass',
});
Class({
name:'ChildClass',
extend: window.ParentClass
});
var m = ChildClass();
expect(m instanceof ParentClass).toBe(true);
});
it("should extend attrs instead of attributing it to prototype", function(){
Class({
name:'ParentClass',
});
Class({
name:'ChildClass',
extend: window.ParentClass,
attrs:{}
});
var m = ChildClass();
expect(m instanceof ParentClass).toBe(true);
});
it("should support multi level inheritance", function(){
Class({ name:'GrandParentClass', });
Class({ name:'ParentClass', extend: window.GrandParentClass, attrs:{} });
Class({ name:'ChildClass', extend: window.ParentClass, attrs:{} });
var m = ChildClass();
expect(m instanceof ChildClass).toBe(true);
expect(m instanceof ParentClass).toBe(true);
expect(m instanceof GrandParentClass).toBe(true);
});
it("should have __super__ object", function(){
Class({ name:'ParentClass', attrs:{} });
Class({ name:'ChildClass', extend: window.ParentClass, attrs:{} });
var m = new ChildClass;
expect(m.__super__.constructor === ParentClass).toBe(true);
});
it("should bind all functions to the instance scope", function(){
Class({name: 'MyClass',
attrs: {
attr: 'value'
fun1: function(){
this.attr = 'function value';
},
}
});
var instance = new MyClass;
instance.fun1();
expect(instance.attr).toBe('function value');
});
});
function Class(config){
var base_namespace = config.namespace === undefined? window: config.namespace;
base_namespace[config.name] = function(){
if(!(this instanceof base_namespace[config.name])){
return new base_namespace[config.name];
}
}
var klass = base_namespace[config.name];
if (config.attrs === undefined && config.extend === undefined){
return;
}
if (config.extend !== undefined){
klass.prototype = new config.extend;
klass.prototype.__super__ = config.extend.prototype;
}
if (config.attrs !== undefined){
klass.prototype = _.extend(klass.prototype, config.attrs);
}
klass.prototype.constructor = klass;
klass.name = config.name;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.