Edit in JSFiddle

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;
}