2

I would like to research and fiddle around with self-modifying functions and knowing that JavaScript has eval and other interesting reflection-ish features, like making a function print its body from the inside, I figured I would like to do some self-modifying function tests with JavaScript.

I want to have a simple function, that, when called, modifies itself according to what ever, any rule.

Like maybe some function could first do a simple console.log and the next time it is called it would do alert instead. This can be obviously achieved with an if, but what I am looking for here is that the actual physical function should first look like this:

function selfm()
{
    console.log('hello')
    // + modify self here somehow
}

And after the first call:

function selfm()
{
    alert('hello')
}

How can I achieve this kind of behavior in its simplest form?

Swiffy
  • 4,401
  • 2
  • 23
  • 49
  • 1
    Or you could just implement a function that accepts a selector function and an array of other functions to invoke. So the selector would choose which one to invoke, then it would be invoked. Clear, easy to maintain/test, no ugly runtime mutations. – zerkms Dec 17 '15 at 08:18
  • 1
    @zerkms That misses my point. I want to make a function that can literally edit itself from the inside when it is called, so that the actual structure of the function changes after the call. The point is also to completely lose the information about what the function looked like before it was called at all. – Swiffy Dec 17 '15 at 08:21
  • 2
    It's not the problem - it's an ugly solution. Explain the original problem that requires such a weird solution. – zerkms Dec 17 '15 at 08:22
  • 2
    Just another example of the XY problem – hindmost Dec 17 '15 at 08:24
  • 2
    @zerkms The original "problem" is that I want to inspect how self-modifying functions work in JavaScript, but I cannot quite come up with a function that is, well, self-modifying. This is just me doing private fiddling, so the ugliness of the solution does not matter. – Swiffy Dec 17 '15 at 08:27
  • `selfm = function() { // this is a new function };` --- that's how you "redefine" a function – zerkms Dec 17 '15 at 08:29
  • `function selfm() { console.log('hello'); selfm = function() { alert('hello'); } }` - no need to go down the evil eval path at all – Jaromanda X Dec 17 '15 at 08:33
  • @JaromandaX I agree that eval is unnecessary unless conversion from strings is required, but your version and the others below allow consumers to use saved references to execute earlier versions after the change. For example, `var original = selfm; selfm(); original();` logs to the console twice instead of calling alert. Without the ability to directly modify function entry points in memory, I think the best we can do in javascript is make `selfm` a constant outer wrapper that executes a mutating inner function reference that's captured in a closure. – rob3c Jul 21 '16 at 04:30

4 Answers4

5

This might not be a great solution, but hope it helps.

function selfm(str){
 this.print = eval("(function a() {"+str+"})") ;
 this.print();
} 

And you can then call onto with whatever string parameter you wish your function to act as.

selfm("console.log('Hello');");
// will print Hello in console.

selfm("alert('Hello');");
// will alert Hello

Still need to test on different browsers. :)

damitj07
  • 2,689
  • 1
  • 21
  • 40
  • That is actually an interesting solution in a sense that it gives me some good ideas as to what exactly why I am trying to achieve here. In a sense it is just eval wrapped into another function, but it makes some good points. – Swiffy Dec 17 '15 at 10:31
1

If you only need it to change itself once, then you could do this:

var selfm = function () {
    console.log('hello');
    selfm = function () {
        alert('hello');
    };
};

The selfm() function would print "hello" to the console the first time, and then change itself into a function that instead shows a "hello" alert every time after that.

This could be useful in cases where there's some complex bit of code that needs to be run, but after it has run one time, every time after that it would produce the same result. You could optimize such a function to just immediately return that same result, instead of re-doing the calculations every time, by using that method.

HiEv
  • 88
  • 7
1
//basic example

let myFunction=function(){
    console.log("previous code!");
    myFunction=new Function("console.log('new code!');");
}

myFunction(); //previous code!
myFunction(); //new code!
  • This is basically a copy of my earlier answer, minus the explanation and without providing code which specifically answers the asker's question. – HiEv Jul 29 '23 at 18:50
0
//Javascript self modifying function

function operation(operator,num1,num2){
  //storing reference 
  let temp=operation; 
  let mod=`"console.log(num1${operator}num2)"`;

  //performing modification 
  operation=new Function("num1,num2",eval(mod));
  operation(num1,num2);

  //restore original reference
  operation=temp;
}

operation("+",10,20); //30
operation("-",20,10); //10
operation("*",10,20); //200
operation("/",20,10); //2