How to do a non-destructive overwrite of a function in javascript

I really don’t like the “non-destructive” expression but I couldn’t come up with a better one.

What?

You want to create a function but you will overwrite the old one. You just want to add some code before or after it.

Example, you create a javascript applet that can be added to web sites you do not own and you want to call a function in the body.onclick() event. Maybe the site already has something in the body.onclick() event and you don’t want to overwrite it because the other developer will be mad at you. You’re stuck!

How?

First of all, don’t panic. Take a deep breath and relax.

Now, you’re ready.

  1. var oldBodyOnClick = body.onclick;
  2. body.onclick = function() {
  3.         // Add your code here!
  4.         alert("Before the old event");
  5.  
  6.         if (oldBodyOnClick != null) {
  7.                 oldBodyOnClick();
  8.         }
  9.  
  10.         // or here!
  11.         alert("After the old event");
  12. }

Could you repeat slower please?

Ok.

First, I assign the body.onclick() event to a new variable.

  1. var oldBodyOnClick = body.onclick;

Second, I create a new function that will be called on the body.onclick() event.

  1. body.onclick = function() {

Third, I add code before the old event

  1. alert("Before the old event");

Fourth, I call the old event if it is not null

  1. if (oldBodyOnClick != null) {
  2. oldBodyOnClick();
  3. }

Third, I add code after the old event

  1. alert("After the old event");

That’s it!

  • BK

    Here come the recuer again! :P Here Comes: THE CLOSURE!

    function FnBuilder(){
    var Old=document.getElementById(“myb”).onclick
    function New(){Old();alert(5678);}
    return New
    }
    document.getElementById(‘myb’).onclick=FnBuilder();
    FnBuilder=null;

  • Boyan

    Nice. Don’t most js libraries take care of this automatically already? Oh, and by the way (nitpick coming), the past tense of “stick” is “stuck” and not “stucked”

  • http://www.javascriptkata.com/ Dan

    @Boyan
    I guess that a lot of librairies can take care of this… but sometimes you don’t have any librairie for a small web site or a bookmarklet…

    Thanks for the correction…

  • http://breakfastdinnertea.co.uk si

    While I don’t like that method of event adding (I think a nice cross-browser addEvent function is far safer / nicer), it’s quite a pretty way of doing it – one good consequence is that you can specify whether yours happens before or after all of the existing methods.

    Another similar “trick” which I like is overriding the alert() function to get rid of potentially missed debug code, like so:

    _alert = alert;
    alert = null;

  • http://synthesis.sbecker.net Scott Becker

    Since you’re not really overwriting the function, but adding before and after callbacks, ActsAsAspect is an elegant way of doing this – http://beppu.lbox.org/articles/2006/09/06/actsasaspect

    Basically, you can take a function or object or class with some existing methods:

    MyObj.go = function() { alert(‘go’); }

    and call actsAsAspect() on it like so:

    actsAsAspect(MyObj);

    then it gets some some extra methods – before, after, & around, which let you add listeners to that function like this:

    MyObj.before(‘go’, function() { alert(‘do this before go() gets called!’) })

    It’s short and sweet, I love that little script.

  • http://cookiecrook.com/ James Craig

    Even without a library, try DOM Level 2 assignment and you won’t overwrite any of these DOM 1 assignments or other DOM 2 events.

  • BK

    What do you mean by DOM Level 2?
    Are you talking about the register event stuff?

  • http://stephansmap.org Stephan Wehner

    Couldn’t get this to work with “console.debug” (which comes with Firebug, for Firefox) — I got “too many recursions” with

    var origcd = console.debug
    console.debug = function(s) {
    origcd(‘console-debug: ‘ + s)
    }
    :
    :
    :
    console.debug(‘test’)

    console.debug writes to a console, that can be viewed with Firebug.

    Stephan

  • http://peachey-schoorl.com/ Potherca

    Since you didn't like the expression “non-destructive overwrite” but couldn’t come up with a better one, you might be interested to know that it is more widely known as “monkey patching” or “duck punching”:

    http://en.wikipedia.org/wiki/Duck_punching

  • http://webdevwonders.com Jens

    Thank you very much for that piece of code! I spent quite some time to find a solution how to extend some of Javascript's built-in functions without simply overwriting it.

  • http://mariuniumopsz.com/ Irimaniumnops

    Sources…

    [...]check below, are some totally unrelated websites to ours, however, they are most trustworthy sources that we use[...]……