5

Suppose I had the following function:

function alertMesg()
{
   alert("This ok function alerts message!");
}

Now at run time I would like to change the alertMesg function to do something else. My thought was to do somehting like this.

var temp = window.alertMesg.toString.replace("ok","great")
temp = temp.replace('function alertMesg()',"");
window.alertMesg = new Function(temp);

Basically, the problem is I have no control over the source in the alertMesg function. I would like to change the function, but I can't actually change the source of it because it is produced server side. That being said, I need it to act differently.

PS: I forgot to mention an important part: I have to keep most of the function. I can't just replace the function out right. I have to keep 95% of the function the way it is, and change the other five percent.

@Barlow Tucker, quixoto, pekka Thanks, for the interest.

Basically, I don't think the proxy idea will work because I am not just adding functionality, I am changing the functionality of the code. I want for example, the third line of the function to be different. In my real life example I have to add a line right in the middle of a function.

seaotternerd
  • 6,298
  • 2
  • 47
  • 58
GC_
  • 1,673
  • 6
  • 23
  • 39
  • possible duplicate of [JavaScript: Overriding alert()](http://stackoverflow.com/questions/1729501/javascript-overriding-alert) – Pekka Aug 12 '10 at 21:58
  • 1
    That duplicate should answer it (See the accepted answer with the "proxy pattern", replace `window.alert()` by your function). – Pekka Aug 12 '10 at 21:59
  • Proxy might allow me to add functionality to this function, but it does not allow me to remove functionality. – GC_ Aug 12 '10 at 22:02
  • i was told that if someone i doing such things, someone else is going to kill some kitten – mykhal Aug 12 '10 at 22:11
  • 1
    Why are you wanting to add/remove functionality? A little more information might help. – Barlow Tucker Aug 12 '10 at 22:20
  • @Grae: The proxy pattern will solve the problem as you have stated it. If your problem is actually more complicated (you want to change the guts of some other function, not just the output of an alert), then please say so. The best answers will likely be different. – Ben Zotto Aug 12 '10 at 22:21

2 Answers2

13

If you must replace the content of a function, it is possible:

function alertMesg()
{
   alert ("This ok function alerts my message!");
}

alertMesg(); // alerts "This ok function alerts my message!"

// do whatever you want to the function here
var temp = alertMesg.toString();
temp = temp.replace('my', 'your');

// now replace the original function
alertMesg=new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}')));

alertMesg(); // alerts "This ok function alerts your message!"

This probably isn't the best way to do what you're trying to achieve, but I can't really suggest anything else unless you provide more details.

Dumb Guy
  • 3,336
  • 21
  • 23
  • I followed at first, but you lost me at the eval. Just calling eval on temp magically changes alertMesg? I tried your source on IE, and got a JavaScript Error. – GC_ Aug 12 '10 at 22:20
  • Hmm...if your function is defined as alertMesg = function(), then you might have to use `alertMesg = eval('('+temp+')');` instead. – Dumb Guy Aug 12 '10 at 22:24
  • Now, I get an object expected error, on the final alertMesg() call. – GC_ Aug 12 '10 at 22:43
  • How about `alertMesg = new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}')));` – Dumb Guy Aug 12 '10 at 22:58
  • It worked! Thank you! You saved me a lot of trouble!!! The reason I needed to do this was because the catch() in the JSF produced JavaScript code catches exceptions in my functions, so if there is a JavaScript error in my code, it crashes parts of the produced code without letting me know. It was a real pain trying to guess what was wrong. I am going to overwrite the catch, and put some of my own code in there. At least, now I will know right away when I crash their code. Rather, than various peaces of the web just not working. – GC_ Aug 13 '10 at 03:02
  • Thanks, for your help. The problem really was a pain, hopefully this will make things a bit easier. – GC_ Aug 13 '10 at 03:04
  • That's a neat technique at least. Not terribly efficient with the back and forth stringifying of course but I'm sure you knew that. You mentioned this might not be the best way. Can you elaborate at all for the use case of wanting to append a new line to a function? Currently I allow users to register an init script for content replaced during AJAX calls to rebind events, etc.. Using an array of function objects, the AJAX code loops through the array, passing the replaced element to the init functions. – That Realty Programmer Guy Aug 19 '17 at 07:53
  • @GaretClaborn Hey, basically, if you override a function, you can do something like this function `newfunction() { oldfunction(); newstuff();}` or you can do `function newfunction() { newstuff(); oldfunction();}` you can't do `newfunction() { half_of_oldfunction(); newstuff(); other_half of_oldfunction()};` – GC_ Jun 15 '18 at 18:51
4

Dynamic code replacement like you're suggesting might work in some cases, but it's a scary road to go down-- fragile, one wrong step and you're busted, and it quickly becomes a maintenance nightmare.

As a commenter said, your cleaner bet is to just wrap the native window.alert and then do the right thing when the string you care about comes through, per the answer here: JavaScript: Overriding alert()

(Insert standard comment here about how you should get your server side people on the same page/team as you on this so you don't need to hack around your own page.)

UPDATE: You're not asking about alert, you're asking about this problem generally. Yes, you could what others are suggesting. But if you have the original code for the function, why not just replace it entirely? If the function you want is a global function called foo(), you can run JS that does:

window.foo = function() {
    // The stuff I know is there (A)
    ...
    // Some new stuff I want to change (B)
    ...
    // More stuff I know is there (C)
}

Which will throw away the original and replace it with your version. This would work reasonably well, although "monkey patching" the stuff in the page definitely comes with some maintenance headaches.

I will definitely note here that if you can't do this for some reason and thus insist on doing textual code replacement in the middle of existing functions, you're abusing the language/environment for the purposes of maintainable anything, and you are truly screwed in multiple ways.

Community
  • 1
  • 1
Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
  • Suppose the original function has part a, part b, and part c. I want the new function to have part a, part b, a new part, and then part c. With the overwriting, I can only have the new function be like new part, part a, part b, part c, or like part a, part b, part c, and then the new part. Unless I am not understanding, the new part I am adding, can not be in the middle of the function with you idea. – GC_ Aug 12 '10 at 22:42
  • I need to add some code to the middle of the function, not the start or end of it. However, thank you, for trying. – GC_ Aug 12 '10 at 22:45
  • The JavaScript function I have to modify is dynamically produced by JSF, server side, and is different on every page. I really need a solution that lets me modify the existing function, because I don't really know what will be in the function ahead of time. It basically follows a pattern, and I know what I need to change each time, but I don't know all the stuff in the function ahead of area I want to change. I do think I can guess all the stuff after that point, if that helps. – GC_ Aug 13 '10 at 02:37