Wednesday, August 1, 2012

jQuery Function Of The Week: proxy

In my JavaScript fundamentals presentations I have a section that talks about scope and how it can become confusing when using jQuery.  The reason for this is becuase jQuery normalizes the this scope in its function calls.  In other words when inside a jQuery method call this usually refers to the DOM elements in the jQuery set.

This can be clearly illustraed in a simple jQuery event callback (note use your browsers console, not jsbin's for the meantime):

JS Bin demo

This can become a problem when we try to write reusable code. Lets say we want to put our event handler into a object and then call it when a user clicks on a link:

JS Bin Demo

If you run the code you'll see that you get "Hello, undefined" instead of "Hello, Homer Simpson". The reason is simple, jQuery used the link as the context of this where no myName property exists. Enter jQuery.proxy.

According to the jQuery Documentation, the proxy function:
Takes a function and returns a new one that will always have a particular context.
This means that by using the $.proxy function we can make our callback run in the proper context, in this case itself:

JS Bin Demo

The change is subtle, but the result is exactly what we want.   Now, at this point you might be asking yourself, "isn't this the same thing as using the apply() or call() methods (mdn apply documentation)?   The answer is yes...and no.  Lets look at how to get the desired result using apply():

JS Bin Demo

If you look closely you'll notice a slight difference, the callback is now invoked in an anonymous function instead of passed directly to the on() method.  This is because the apply method invokes the function immediately whereas jQuery's proxy function only returns a reference function for later invocation.   This is a bit nicer because it makes for slightly more terse code.

In addition the proxy() function does a few more things:

  • it makes sure that the function passed in is actually a function
  • it assignes a unique ID to the function.  This is very important because when trying to unbind a function you may not be unbinding the proper function if you are passing in the function to the off() method.  Its best to always use namespaced events when using on() and off() with $.proxy().
Fork me on GitHub