Since Rails announced both jQuery and CoffeeScript as the defaults in version 3.1, I decided it was high time I starting learning both. I had always known that jQuery bound the
this keyword in event handlers to the DOM object. Something I found totally confusing and unacceptable to someone dealing with their own objects to encapsulate behavior. Today I found two ways of dealing with my problem, a jQuery way and a CoffeeScript way. First a code example.
class MyObject constructor: -> @myDomElement = $('#myDomElement') @._initBehavior() handler: (event) -> console.log(this) false _initBehavior: -> $(window).resize @handler jQuery -> window.myObject = new MyObject();
Here is a simple class using CoffeeScript's methods. It initializes itself with a static property
this.myDomElement to some DOM element on the page with an id of "myDomElement". It then attaches an event handler to the window's resize event and logs
this along the way. Simple stuff, the only problem will be that the object logged will not be an instance of MyObject, but the raw DOM element, in this case the window object. One way of fixing this is to use jQuery's proxy function like so
_initBehavior: -> $(window).resize jQuery.proxy(@handler,this)
This works, but seems a little verbose to me and can clutter up your event initialization code. The other way is to use CoffeeScript's fat arrow operator. An excerpt from their project page explains it well.
The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with bind. Functions created with the fat arrow are able to access properties of the this where they're defined.
So all we have to do is change
=> for any of our callbacks or event handlers and now
this is our own object and not the DOM element. Hot damn!
class MyObject constructor: -> @myDomElement = $('#myDomElement') @._initBehavior() handler: (event) => console.log(this) false _initBehavior: -> $(window).resize @handler jQuery -> window.myObject = new MyObject();