Skip to content

Instantly share code, notes, and snippets.

@nijikokun
Last active December 27, 2015 21:59
Show Gist options
  • Save nijikokun/7396092 to your computer and use it in GitHub Desktop.
Save nijikokun/7396092 to your computer and use it in GitHub Desktop.
The easiest, and most comprehensible class system for JavaScript using prototypal inheritance and Object.create. Also contains an additional chaining method, that isn't required but simplifies your code. Outputs the cleanest objects as far as Class Systems go.

Hello,

After looking for a simple Class system in JavaScript, and looking at all the horrible libraries, forced upon terrible syntax, cluttered objects and prototypes... I'd like to introduce a simple alternative.

This is a very bare-bones, and yet one of the more powerful class systems in JavaScript. Built on-top of Object.create and prototype inheritance using the methods that everyone suggests is the best way to do classes in JavaScript ported over to a nicer syntax.

It doesn't clutter the properties or the prototype aside from a single method which is extends, and even this method is sugar and not required!

Check out zoo.js for an in-depth example of how to use Class. No matter how deep down the rabbit hole you go, it should keep references so you can do instanceof checks on children of a parent of a grand-parent and so forth.

Zoo.js Instance Graph

Graph

Here we can see that you still have <anon>() methods (don't worry, the reference to do instanceof checks still exists, the naming just looks bad when graphed) which is hard to get around when sugaring the prototype syntax. Trust me, I tried to avoid it.

Last notes

If you can find a simpler way, let me know and I'll update it.

if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
function Class (parent, object) {
if (!object) parent = (object = parent, undefined);
if (!parent) {
object.extend = function (method) {
return Class(object, method);
};
return object;
}
var instance = function () {
var args = Array.prototype.slice.call(arguments);
var amount = parent.apply(this, args);
return object.apply(this, args);
};
Class.extend(parent, instance);
instance.extend = function (method) {
return Class(instance, method);
};
return instance;
}
Class.extend = function (parent, object) {
object.prototype = Object.create(parent.prototype);
object.prototype.constructor = object;
}
Class.chain = function (object) {
return function () {
var args = Array.prototype.slice.call(arguments);
var result = object.apply(this, args);
return typeof result != 'undefined' ? result : this;
};
};
var Animal = Class(function (name) {
this.name = name;
});
// Optional Extension Method
//
// This is sugar for:
//
// var Tiger = Class(Animal, ... main method ...);
//
// If you prefer to not clutter and extend the function passed through Class,
// remove lines 18 - 20 && 33 - 35.
var Tiger = Animal.extend(function (name) {
this.color = 'Orange';
});
// Chaining functionality like that of jQuery.
// Takes the method, invokes with passed arguments along with this as the context, and returns this as the context.
Tiger.prototype.setColor = Class.chain(function (color) {
this.color = color;
});
console.log(new Tiger('Tiger').setColor('white') instanceof Animal);
@nijikokun
Copy link
Author

If you want to throw in events this works great with: https://gist.github.com/Nijikokun/7298768 just add Class.observe = observe function here before Class.chain and inside of the invoking method do Class.observe(this) and you are done.

@supermensa
Copy link

How would you deal with extending/calling a super method from a 'subclass'?

@nijikokun
Copy link
Author

this doesn't deal with super / parent reference in such a manner, however it is not hard to implement you could extend it by adding object.prototype.parent = parent; inside of Class.extend

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment