Created
July 5, 2012 15:55
-
-
Save theefer/3054503 to your computer and use it in GitHub Desktop.
Helper mixin to allow invoking the super method using the prototype chain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
/** | |
* Invoke the super method corresponding to the caller (child-)method. | |
* | |
* Typically useful to call super constructors or destructors. | |
* | |
* @param args The arguments object of the caller method. | |
* @param superArguments Optional arguments to call the super method with. | |
* @return The result of calling the super method. | |
*/ | |
invokeSuper: function(args /*, superArguments... */) { | |
if (!args) { | |
throw new Error("Missing arguments object in invokeSuper"); | |
} | |
var superMethodArguments; | |
if (arguments.length > 1) { | |
superMethodArguments = Array.prototype.splice.call(arguments, 1); | |
} else { | |
superMethodArguments = args; | |
} | |
function getParentPrototype(prototype) { | |
// this reference is setup by Backbone | |
return prototype.constructor.__super__; | |
} | |
// lookup the name of the called method (bit tedious, innit?) | |
// FIXME: more efficient lookup? cache name? | |
function findMethodProperties(obj, func) { | |
for (var propName in obj) { | |
if (obj.hasOwnProperty(propName) && obj[propName] === func) { | |
return {object: obj, name: propName}; | |
} | |
} | |
var parent = getParentPrototype(obj); | |
if (parent) { | |
return findMethodProperties(parent, func); | |
} | |
} | |
var childMethod = args.callee; | |
var thisPrototype = this.constructor.prototype; | |
var methodProperties = findMethodProperties(thisPrototype, childMethod); | |
if (!methodProperties) { | |
throw new Error("Method name not found, is the function really on the object?"); | |
} | |
// call super method (if there is one) | |
var methodName = methodProperties.name; | |
var parentPrototype = getParentPrototype(methodProperties.object); | |
var superMethod = parentPrototype && parentPrototype[methodName]; | |
if (superMethod) { | |
return superMethod.apply(this, superMethodArguments); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment