How can dynmically change a line of a JavaScript function?
Asked Answered
G

2

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.

Gusty answered 12/8, 2010 at 21:56 Comment(6)
possible duplicate of JavaScript: Overriding alert()Perfumer
That duplicate should answer it (See the accepted answer with the "proxy pattern", replace window.alert() by your function).Perfumer
Proxy might allow me to add functionality to this function, but it does not allow me to remove functionality.Gusty
i was told that if someone i doing such things, someone else is going to kill some kittenHeber
Why are you wanting to add/remove functionality? A little more information might help.Possessive
@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.Brelje
S
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.

Silveira answered 12/8, 2010 at 22:12 Comment(8)
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.Gusty
Hmm...if your function is defined as alertMesg = function(), then you might have to use alertMesg = eval('('+temp+')'); instead.Silveira
Now, I get an object expected error, on the final alertMesg() call.Gusty
How about alertMesg = new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}')));Silveira
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.Gusty
Thanks, for your help. The problem really was a pain, hopefully this will make things a bit easier.Gusty
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.Localism
@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()};Gusty
B
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.

Brelje answered 12/8, 2010 at 22:16 Comment(3)
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.Gusty
I need to add some code to the middle of the function, not the start or end of it. However, thank you, for trying.Gusty
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.Gusty

© 2022 - 2024 — McMap. All rights reserved.