4 ms·
Why jQuery.proxy rocks my world
- mrspeaker 15y agoI 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 15y agoHmm... Nice idea. But what if the closure is to be called from somewhere else as well?
- trezor 15y agoNice 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.
- gmac 15y agoSince 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 15y agoOther parts of the app use Backbone. FBNotificationWatcher is a simple implementation based on JS.Class - http://jsclass.jcoglan.com/classes.html http://jsclass.jcoglan.com/classes.html
- footless 15y agoJSClass seems to provide this too :) http://jsclass.jcoglan.com/binding.html http://jsclass.jcoglan.com/binding.html
- cominatchu 15y agoIf underscore is already loaded into the browser cache for other pages then you should be able to use it for free here then and not need jquery.proxy
- jashkenas 15y agoRight, You may want to prefer using _.bind and _.bindAll to jQuery.proxy, because the Underscore functions delegate to the native Function.prototype.bind, if it exists.
- deleted 15y ago[deleted]
- newhouseb 15y agoIIRC, .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 15y agoThe 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.
- emehrkay 15y agoThat 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.
- cfq 15y agoThis 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_Objects/Function/call https://developer.mozilla.org/en/JavaScript/Reference/Global... https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply https://developer.mozilla.org/en/JavaScript/Reference/Global...
- udp 15y agoOr 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 15y agoExactly. It's a Function.bind clone: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind https://developer.mozilla.org/en/JavaScript/Reference/Global... Unfortunately, bind is a 5th edition feature, not widely available.
- bialecki 15y agoI 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).
- dguaraglia 15y agoI 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.