I'm building a module in the context of an existing library. Some of the library's functionality — specifically, LIBRARY.module.add
(for the sake of example: the actual functionality's much more elaborate) —, which can be triggered in all sorts of scenarios, will destroy my module's UX, so I need to interrupt it to take account of my module's esoteric concerns.
I'm not allowed to re-write any part of the original library, and I'm not allowed to duplicate functionality which is supposedly covered by the library.
Existing code is something like this:
LIBRARY.moduleX = {
two : 2,
addToTwo : function(addAnd){
return this.two + addAnd;
}
}
A key concern here is that LIBRARY
's modules are all written in literal object notation and their methods rely on this
. Another concern is that the code base is continuously in flux. I can't rely on addToTwo
's arity or anything like that (in case someone extends it to take multiple operands or whatever).
So I've written this to execute as part of my component's initialization:
void function handleModuleX(){
// Keep a reference before rebinding
var LIBRARY_moduleX_addToTwo = LIBRARY.moduleX.addToTwo;
// Restores the original binding
function rebind(){
LIBRARY.moduleX.addToTwo = function(){
return LIBRARY_moduleX_addToTwo.apply(LIBRARY.moduleX, arguments);
}
}
// Rebind to consider local logic
LIBRARY.moduleX.addToTwo = function handleEsotericLogic(){
if(unresolvedConcerns){
stuff();
}
else {
rebind();
LIBRARY.moduleX.addToTwo();
}
}
}();
This appears to work. My concern is ultimately with the safety and legibility of the rebinding:
addToTwo
? rebind
can be written in to the else
statement — it's only hoisted out for clarity)?A bit more research lead me to underscore's bind
method, which does basically the same thing I did to polyfill ECMAScript 5's native Function method of the same name — which appears to be the only way I can avoid the 2 closures involved in the implementation above. So now my code is more verbose — because I just really didn't like the idea of calls on the library's method bouncing through my code on stack trace if possible (it's like I never touched it!):
function rebind(){
if(Function.prototype.bind){
LIBRARY.moduleX.addToTwo = LIBRARY_moduleX_addToTwo.bind(LIBRARY.moduleX);
}
else {
LIBRARY.moduleX.addToTwo = function(){
return LIBRARY_moduleX_addToTwo.apply(LIBRARY.moduleX, arguments);
}
}
}