By

Understanding the Fat Arrow(=>) in CoffeeScript

I've been using CoffeeScript for quite a while without paying much attention to how it actually works under the hood.

One example is the fat arrow(=>). I use it a lot, and despite having an idea as to how it might be working in javascript, I haven't looked at the code generated.

Finally, after a ridculously long time, I decided to get my hands dirty and look at the Javascript code being generated.

What it does

Quoting CoffeeScripts website

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

Lets have a look at it in action.

class A  
  LOGIN_ID = "#login"

  constructor: ->
    @bindAll()

  bindAll: ->
    $(LOGIN_ID).click @a

  a: =>
    console.log @b()
  b: ->
    'testing'


a = new A()  

In the example above, we're setting an event handler on the click event of a DOM element. By default, the context of the event handler would have been that of the the object triggering the event, which in this case would be $('#login')

The fat arrow is used while defining the function a because it is further invoking another function b defined within class A. We would have received a nasty error while triggering the event if a regular function(->) declaration was used because b doesn't exist in the context of the DOM element

The Javascript generated

Lets define a class with a single function defined with the aid of the fat arrow.

class A  
  b: =>
    'testing'

We get the following Javascript code.

var A,  
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };


A = (function() {  
  function A() {
    this.b = __bind(this.b, this);
  }

  A.prototype.b = function() {
    return 'testing';
  };

  return A;

})();

Understanding whats happening

Lets have a look at the code above by breaking it down

var A;

A = (function() {  
 ...

 return A;
})();

A is being assigned an anonymous function that will be immediately invoked. A will be assigned the value of whatever the anonymous function returns.

Lets move on to the rest of the anonymous function definition.

function A() {  
    this.b = __bind(this.b, this);
  }

  A.prototype.b = function() {
    return 'testing';
  };

Besides assigning the prototype of A a property b(Note: this much would have sufficed if the regular arrow was used ), we assign a property b in A the output of whatever is generated after calling the __bind function passing this.b which would actually be A.prototype.b in this case along with this, the current context of where the code should be executed.

__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };  

The apply function can be used on any function and accepts the context under which the function should be invoked via this being passed as an argument as well as an array of arguments. Through the use of the this Coffeescript ensures that the code is executing under the intended context.

CoffeeScript handles the second argument rather intelligently as it utilizes the arguments which is available in any function. It is essentially an array of the args passed to a function along with a couple of properties. Arguments can further be read here.

Summarizing

Summarizing whats happening. An anoymous function is declared and immediately invoked. Within the anonymous function, a function A is defined and a property of its protoype(A.prototype.b) is assigned the code equivalent of whatever functionality we define in the coffeescript function body. Within the scope of the function A, a property is defined which invokes the property defined in the protype the apply method while passing the current context along. This ensures that the executed code is always under the correct namespace.

Pretty cool!

comments powered by Disqus