

Why jQuery.proxy rocks my world - makuchaku
http://www.makuchaku.in/blog/why-jquery-proxy-rocks-my-world

======
cfq
This sort of thing happens a lot when people learn jQuery but not Javascript.
This fascinating "jQuery feature" is just a wrapper for JavaScript's built-in
functions call and/or it's brother apply.

[https://developer.mozilla.org/en/JavaScript/Reference/Global...](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call)

[https://developer.mozilla.org/en/JavaScript/Reference/Global...](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply)

~~~
udp
Or rather, it returns a new function that wraps call/apply with a "baked in"
value of 'this', so that it can be passed as a callback and retain the correct
'this'. That's a bit different than just being a wrapper for them - it's
shorthand for using something like "var that = this" and a closure.

When we start seeing people using (jQuery.proxy(xxx)()) - then they've learned
too much jQuery and not enough Javascript :-)

~~~
andos
Exactly. It's a Function.bind clone:

[https://developer.mozilla.org/en/JavaScript/Reference/Global...](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind)

Unfortunately, bind is a 5th edition feature, not widely available.

------
gmac
Since the app is apparently written using backbone.js, the _.bindAll method
would be a neater solution here (as I see one of the commenters on the post
points out).

~~~
makuchaku
Other parts of the app use Backbone. FBNotificationWatcher is a simple
implementation based on JS.Class - <http://jsclass.jcoglan.com/classes.html>

~~~
footless
JSClass seems to provide this too :) <http://jsclass.jcoglan.com/binding.html>

------
mrspeaker
I prefer to just use a closure - but that just might be because I've used them
so long that my brain thinks it looks nicer.

Another nice context-setting trick is to set the context manually when you do
ajax requests - then callbacks will have the context of the object you did the
request in:

    
    
      var myobj = {
        done: "I'm done.",
        load: function(){
          $.ajax({
            context: this,
            success: function(){
              alert(this.done);
            }
          });
        }
      };

~~~
makuchaku
Hmm... Nice idea. But what if the closure is to be called from somewhere else
as well?

------
bialecki
I don't know when jQuery added this method, but for the longest time they
didn't have it and made you use closures even while most other javascript
libraries had similar methods. Their argument was that you should know what's
going on rather than just using a convenience method all over the place (and
likely in situations where you don't need it).

------
emehrkay
That looks like a Class in MooTools. Difference seems to be that it is a
single lib dependency and "proxy" is called "bind"

It would look something like this

    
    
        var FBNotificationWatcher = new Class({
            Implements: [Options],
            
            options: {
                timeout: 500,
                url: 'http://dot.com',
                onRequestComplete: function(response){}
            },
            
            initialize: function(options){
                this.setOptions(options);
                
                this.request = new Request({
                    url: this.options.url,
                    onComplete: function(resp){
                        this.processNotifications(resp);
                        this.options.onRequestComplete(resp);
                    }.bind(this)
                });
                
                this.getNotifications();
            },
            
            getNotifications: function(){
                this.request.send({//data});
                
                return this;
            },
            
            processNotifications: function(rawNotificationData){
                //do stuff
                this.getNotifications.delay(this.options.timeout, this);
            }
        });
    

I'll check out backbone if I'm doing some jQuery dev.

------
dguaraglia
I guess this is kind of surprising/interesting if you haven't taken a
functional programming course in university, but as others have pointed out,
proxy is just a simpler wrapper on top of 'apply'/'call'. You should read the
docs on those two functions, as the difference in the way they work is subtle
but worth understanding.

------
newhouseb
IIRC, .bind(this) was used in the exact same way in mootools years and years
ago, and maybe even in Prototype before that.

Oh how I wish mootools had won the JS library war...

~~~
jcampbell1
The difference is that MooTools and Prototype modify the built in Function.
Because of this, old versions of MooTools, and Prototype don't play nice with
current browsers. This a a big reason jQuery won the war. function() {}.bind()
is more convenient and cleaner, but $.proxy() will work regardless of whether
Microsoft incorrectly implements a built in bind in their latest browser.

------
trezor
Nice technique but it definitely illustrates the problems which Javascript's
ill-defined this-keyword brings about (which was discussed here a few days
ago).

This same problem could easily have been solved by setting a private variable
(self, _this, cx, whatever) to this upon instantiation and referring to that
instead of this.

In fact, I find myself using that technique (using self-defined variables
instead of context) , especially for namespacing.

    
    
        var myNamespace = {};
        (function(cx) {
            cx.myClass = function() {
                var self = this;
                self.action = function() {
                    self.foo = "bar";
                }
            };
        })(myNamespace);
    

It makes your code easier to refactor with fewer hard-references to maintain.
I'm about to completely give up any usage of "this" for a "var self = this;"
upon object-creation.

Javascript context-handling is really just too messed up to be dependent on,
and while it allows for lots of "cute" hacks, I personally find it creating a
lot more problems than it solves.

