Let\'s say I have var a = function() { return 1; }. Is it possible to alter a so that a() returns 2? Perhaps by editing a
I used something like this to modify an existing function whose declaration was not accessible to me:
// declare function foo
var foo = function (a) { alert(a); };
// modify function foo
foo = new Function (
"a",
foo.toSource()
.replace("alert(a)", "alert('function modified - ' + a)")
.replace(/^function[^{]+{/i,"") // remove everything up to and including the first curly bracket
.replace(/}[^}]*$/i, "") // remove last curly bracket and everything after<br>
);
Instead of toSource() you could probably use toString() to get a string containing the function's declaration. Some calls to replace() to prepare the string for use with the Function Constructor and to modify the function's source.
var a = function() { return 1; }
alert(a()) // 1
a = function() { return 2; }
alert(a()) // 2
technically, you're losing one function definition and replacing it with another.
You can change functions like other objects
var a1 = function(){return 1;}
var b1 = a1;
a1 = function(){
return b1() + 1;
};
console.log(a1()); // return 2
// OR:
function a2(){return 1;}
var b2 = a2;
a2 = function(){
return b2() + 1;
};
console.log(a2()); // return 2
Can you not just define it again later on? When you want the change try just redefining it as:
a = function() { return 2; }
All feasible solutions stick to a "function wrapping approach". The most reliable amongst them seems to be the one of rplantiko.
Such function wrapping easily can be abstracted away. The concept / pattern
itself might be called "Method Modification". Its implementation definitely
belongs to Function.prototype. It would be nice to be backed
one day by standard prototypal method modifiers like before,
after, around,
afterThrowing and afterFinally.
As for the aforementioned example by rplantiko ...
function a () { return 1; }
// redefine
a = (function () {
var _a = a;
return function () {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
};
})();
a(); // --> gives 2
... and making use of [around], the code would transform to ...
function a () { return 1; }
console.log("a : ", a);
console.log("a() : ", a());
a = a.around(function (proceed, interceptor, args) {
return (proceed() + 1);
});
console.log("a : ", a);
console.log("a() : ", a());
I am sticking to jvenema's solution, in which I don't like the global variable "old". It seems better to keep the old function inside of the new one:
function a() { return 1; }
// redefine
a = (function(){
var _a = a;
return function() {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
}
})();
a() // --> gives 2