Overriding jQuery/JavaScript functions using closures

Function overriding is an important feature in any programming language. In advanced languages like .NET, Java, it can be accomplished easily through a set of key words. But this is not the same in JavaScript and this is where closures come to your rescue.

This article is not something new. Infact, it is a part of every JavaScript geek's  toolkit, which does not have much exposure. So just wanted to throw some light on it. (If you are not very clear of closures, please visit this article and come back).

Let us take a vey simple example. Assume that you have a button, for which a click event is bound.

<input type="button" id="btnTest" value="Test Button"/>

var originalClick=function(e){ 
    e.preventDefault(); 
    console.log('original button click'); 
}; 
 
$(document).ready(function() { 
    $('#btnTest').click(originalClick); 
}); 

Now, if there is some requirement change and you need to add extra functionality to this button click, then instead of messing up its method, you can extend the originalClick method using closures, like this:

(function() { 
    var extendedClick= originalClick; 
    originalClick= function() { 
        console.log('Extending Test Button click'); 
        return extendedClick.apply(this, arguments); 
    }; 
})(); 

The above code is nothing but a self executing anonymous function (gets executed immediately after its definition). In the first line, we are storing the actual function in a variable 'extendedClick' (we'l use this later). Then we are creating a function with the same name as our original button click function (originalClick).

In the inner function, we are writing our extended logic and executing 'extendedClick' using .apply() method. (passing 'this' as first param to .apply() makes sure that the context is still the same as original method). So the entire code would be:

var originalClick=function(e){
    e.preventDefault();
    console.log('original button click');
};
 
(function() {
    var extendedClick= originalClick;
    originalClick= function() {
        console.log('Extending Test Button click');
        return extendedClick.apply(this, arguments);
    };
})(); 
 
$(document).ready(function() {
    $('#btnTest').click(originalClick);
}); 

Thats it! Your method is now overridden!! Ok, now let us see what exactly happened.

As per the definition of closure, we have 2 functions which are nested and extendedClick is a local variable. The outer function is a self executing one. During its execution, ‘extendedClick’ is obviously available inside the inner function ‘originalClick’, since it is defined in the parent context. The magic of closure comes after the outer anonymous function is executed. How?

When you click on button, the overwritten ‘originalClick’ function will be fired, which will print the console statement ‘Extending Test Button click’. Then the ‘extendedClick’ function, which has a copy of the first ‘originalClick’ function, will be fired. But why is it still accessible? The variable ‘extendedClick’ is private to the outer anonymous function, which means, it should have been destroyed after the outer function executed. But it is still accessible, which is the power of closure.

(Q) How can I override core jQuery methods using this concept?
(A) Ben Nadel
explained it clearly in his article, which I happened to see while I started this article. It is the same concept, but still I wanted to write and explain in layman’s terms. Thanks to Ben for his great blog posts and for quick turn out in times of need.

Using this technique, you can override even $(document).ready function! This would help you the most when you are in a maintenance project and have to do bulk changes in code with minimal impact.

Happy coding :)

Scope problems with JavaScript setInterval & setTimeout? Use closures!

JavaScript closures is one of those topics which, I always thought, is beyond my head. Though several articles explain the concept, somehow, I was often confused.

I was working on a thick client application, which heavily uses lot of jQuery and JavaScript. I need a client side timer to run periodically, to keep user's session alive and so I was using JavaScript's native "setInterval()" method for my timer. Everything was fine, till I suddenly faced a weird problem.

Suppose, you have created a  global function which is to be fired periodically. In simple JS, it can be written as:

var timer=function (){ 
    console.log('my timer'); 
}; 
var timerId=setInterval('timer();',1000); 

This works perfectly well. Here the function "timer()" is at a window level and has global scope. So no issues so far.

However, to clean up the code, if you follow any of these patterns,  you will have good code, but setInterval will not work! See the below code for more clarity:

var TestObject=function(){ 
    var timerId; 
    this.timer=function(){ 
        console.log('test timer'); 
    }; 
    this.startTimer=function(){ 
        timerId=setInterval(function(){ 
            this.timer(); 
        },1000); 
    }; 
    this.stopTimer=function(){ 
        clearInterval(timerId); 
    }; 
}; 
 
var obj=new TestObject(); 
obj.startTimer(); 
obj.stopTimer(); 

In the above code, TestObject is the class which is holding the entire code, so that all my functions are not exposed to global window object. "timer()" is a public function which will be fired periodically and "startTimer()" is the function which will trigger the timer.

If you run the above code (you can quickly try in firebug console), you will get a JavaScript error - "this.timer is not a function". The reason is, setInterval() function will take the scope to window object and this will check for "timer()" at window level. Since you are wrapping it in "TestObject", "timer()" will not be found. To solve this scope problem, you need to use closures and store the instance of the class. So the "startTimer()" function should be like:

this.startTimer=function(){ 
      var inst=this; 
      console.log('startTimer this: ',this); 
      timerId=setInterval(function(){ 
          console.log('setInterval this: ',this); 
          inst.timer(); 
      },1000); 
}; 

The above code has two console statements. The “this” keyword in the first console statement prints the instance of TestObject, while the “this” keyword in setInterval function prints “window” object. This shows that setInterval function will take the scope to window level and hence it is not able to find “this.timer” in the first snippet.

Notice that we are storing the instance of TestObject class in a local variable "inst". Also notice that setInterval is using an anonymous function, which is forming a closure. In this anonymous funtion, we are able to access timer() function using "inst.timer()". This would solve the scope problem! setInterval function will be called for every 1 second and it will always have access to “inst.timer()”. This is the power of closures.

To explain closures in my words,  when there are nested functions, the child function will have access to local variables of parent function(which is as expected). But after the parent function has executed, the child function, when called explicitly, will still have access to the local variable of parent function. JavaScript garbage collector will not clear the value of the variable.

For a graphical explanation of JavaScript closures in jQuery context, please check BenNadel's blog. Ben explains the concept of closures very clearly in this article.

Happy coding :)