Example usage:
var MyClass = function () {
this.count = 0;
}
.extends(SuperClass)
.proto({
myMethod: function() {
this.count += MyClass.CONSTANT;
// ...
},
})
.class({
CONSTANT: 123,
});
We make use of the fact that ECMAScript 5 allows trailing commas in object literals. The class definition starts with a function expression (a function declaration does not allow you to invoke methods) and then invokes methods on it to extend a superclass, add methods and add class properties.
This is the code that makes the above work:
(function() {
function copyOwnTo(source, target) {
Object.getOwnPropertyNames(source).forEach(function(propName) {
Object.defineProperty(target, propName,
Object.getOwnPropertyDescriptor(source, propName));
});
return target;
}
Function.prototype.extends = function (superClass) {
var thisProto = Object.create(superClass.prototype);
// At the very least, we keep the "constructor" property
// At most, we preserve additions that have already been made
copyOwnTo(this.prototype, thisProto);
this.prototype = thisProto;
return this; // enable chaining
};
Function.prototype.proto = function (protoProps) {
copyOwnTo(protoProps, this.prototype);
return this; // enable chaining
}
Function.prototype.class = function (classProps) {
copyOwnTo(classProps, this);
return this; // enable chaining
}
}());
Note: This pattern is more a proof of concept than something I would use in practice. But I like that this kind of thing can be done in JavaScript.
Related reading: