Can you alter a Javascript function after declaring it?

Viewed 64762

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 property of the a object, since every function is an object?

Update: Wow, thanks for all the responses. However, I'm afraid I wasn't looking to simply reassign a variable but actually edit an existing function. I am thinking along the lines of how you can combine partial functions in Scala to create a new PartialFunction. I am interested in writing something similar in Javascript and was thinking that the existing function could perhaps be updated, rather than creating an entirely new Function object.

13 Answers

You can do all kinds of fun stuff with javascript, including redefining functions:

let a = function() { return 1; }
console.log(a()); // 1
    
// keep a reference
let old = a;
   
// redefine
a = function() {
  // call the original function with any arguments specified, storing the result
  const originalResult = old.apply(old, arguments);
  // add one
  return originalResult + 1;
};

console.log(a()); // 2

Voila.

Edit: Updated to show this in a crazier scenario:

let test = new String("123");
console.log(test.toString()); // logs 123
console.log(test.substring(0)); // logs 123
String.prototype.substring = function(){ return "hahanope"; }
console.log(test.substring(0)); // logs hahanope

You can see here that even though "test" is defined first, and we redefine substring() afterwards, the change still applies.

Side note: you really should reconsider your architecture if you're doing this...you're going to confuse the crap out of some poor developer 5 years down the road when s/he's looking at a function definition that's supposed to return 1, but seems to always return 2....

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.

let a = function() { return 1; }
console.log(a()) // 1

a = function() { return 2; }
console.log(a()) // 2

technically, you're losing one function definition and replacing it with another.

How about this, without having to redefine the function:

var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2

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

const createFunction = function (defaultRealization) {
  let realization = defaultRealization;

  const youFunction = function (...args) {
    return realization(...args);
  };
  youFunction.alterRealization = function (fn) {
    realization = fn;
  };

  return youFunction;
}

const myFunction = createFunction(function () { return 1; });
console.log(myFunction()); // 1

myFunction.alterRealization(function () { return 2; });
console.log(myFunction()); // 2

Absolutely. Just assign to it a new function.

Can you not just define it again later on? When you want the change try just redefining it as:

a = function() { return 2; }
Related