function callSlice(array, argument) {
return Array.prototype.slice.call(array, argument);
}
function apply(method, args) {
return method.apply(null, args);
}
function applyWithSelf(method, self, args) {
args = callSlice(args, 0);
args.unshift(self); //make self first argument
return apply(method, args);
}
function push(array, arg) {
return array.push(arg);
}
function log() {
var args = Array.prototype.slice.call(arguments);
console.log(args);
}
//methodsInitializer: a function that returns methods for the new object
//initArgs: initialization arguments for the methodsInitializer
//superObject: an optional object to inherit methods
function objMaker(methodsInitializer, initArgs, superObject) {
var methods = apply(methodsInitializer, initArgs);
function dispatch(methodName, callSuper, self) {
self = self || dispatch; //if self given use it, otherwise use this function
if (!callSuper) {
var method = methods(methodName);
if (method) {
return function () {
return applyWithSelf(method, self, arguments);
};
}
}
if (superObject) { //re-call with superObject (this can happen recursively)
return function () {
//when calling super, make sure self is set to the method receiver
return apply(superObject(methodName, false, self), arguments);
}
}
throw 'Method ' + methodName + ' not known';
}
return dispatch;
}