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