I came up with a way that will allow you to use a pseudo keyword Super by changing the execution context (A way I have yet to see be presented on here.) The drawback that I found that I'm not happy with at all is that it cannot add the "Super" variable to the method's execution context, but instead replaces it the entire execution context, this means that any private methods defined with the method become unavailable...
This method is very similar to the "eval hack" OP presented however it doesn't do any processing on the function's source string, just redeclares the function using eval in the current execution context. Making it a bit better as both of the methods have the same aforementioned drawback.
Very simple method:
function extend(child, parent){
var superify = function(/* Super */){
// Make MakeClass scope unavailable.
var child = undefined,
parent = undefined,
superify = null,
parentSuper = undefined,
oldProto = undefined,
keys = undefined,
i = undefined,
len = undefined;
// Make Super available to returned func.
var Super = arguments[0];
return function(/* func */){
/* This redefines the function with the current execution context.
* Meaning that when the returned function is called it will have all of the current scopes variables available to it, which right here is just "Super"
* This has the unfortunate side effect of ripping the old execution context away from the method meaning that no private methods that may have been defined in the original scope are available to it.
*/
return eval("("+ arguments[0] +")");
};
};
var parentSuper = superify(parent.prototype);
var oldProto = child.prototype;
var keys = Object.getOwnPropertyNames(oldProto);
child.prototype = Object.create(parent.prototype);
Object.defineProperty(child.prototype, "constructor", {enumerable: false, value: child});
for(var i = 0, len = keys.length; i<len; i++)
if("function" === typeof oldProto[keys[i]])
child.prototype[keys[i]] = parentSuper(oldProto[keys[i]]);
}
An example of making a class
function P(){}
P.prototype.logSomething = function(){console.log("Bro.");};
function C(){}
C.prototype.logSomething = function(){console.log("Cool story"); Super.logSomething.call(this);}
extend(C, P);
var test = new C();
test.logSomething(); // "Cool story" "Bro."
An example of the drawback mentioned earlier.
(function(){
function privateMethod(){console.log("In a private method");}
function P(){};
window.C = function C(){};
C.prototype.privilagedMethod = function(){
// This throws an error because when we call extend on this class this function gets redefined in a new scope where privateMethod is not available.
privateMethod();
}
extend(C, P);
})()
var test = new C();
test.privilagedMethod(); // throws error
Also note that this method isn't "superifying" the child constructor meaning that Super isn't available to it. I just wanted to explain the concept, not make a working library :)
Also, just realized that I met all of OP's conditions! (Although there really should be a condition about execution context)