Scope in CoffeeScript - actionanand/coffeescript-practice GitHub Wiki
Introduction
Similar to JavaScript, CoffeeScript is a lexically scoped language. Put simply, it allows member functions (or child functions, methods etc.) to access their parent (object, function, class etc.). This works differently in different languages, but the principle remains the same - every inner level can access its outer levels.
In terms of CoffeeScript, this means that we don't need to write var
before declaring a variable (we can't event if wanted to, trying to access var
is reported as an error in CoffeeScript). Additionally, all CoffeeScript output is wrapped in an anonymous function. As the documentation says:
This safety wrapper, combined with the automatic generation of the
var
keyword, make it exceedingly difficult to pollute the global namespace by accident.
This behavior can be circumvented by directly accessing the window
object and attaching properties to it. A cleaner alternative would be to use the CommonJS exports
/ module.exports
approach. During the course, I decided to go for the window
approach, for simplicity's sake.
Differences between JavaScript and CoffeeScript
One confusing aspect of JavaScript is its behavior when using closures (for example, for callbacks). While using callbacks (and closures in general) follows the same behavior in CoffeeScript, it has one additional feature to help normalize* this behavior - the =>
fat arrow operator. Essentially, it does the var self = this;
"hack" automatically (although a bit differently):
CoffeeScript source
Account = (customer, cart) ->
@customer = customer
@cart = cart
$('.shopping_cart').bind 'click', (event) =>
@customer.purchase @cart
Compiled JavaScript
var Account;
Account = function(customer, cart) {
this.customer = customer;
this.cart = cart;
return $('.shopping_cart').bind('click', (function(_this) {
return function(event) {
return _this.customer.purchase(_this.cart);
};
})(this));
};
In a manner of speaking, the fat arrow "transfers" the parent scope to the closure, preserving the context of @
(this
).
Resources
- Scope in the official documentation - http://coffeescript.org/#lexical-scope
- Fat arrows in the official documentation - http://coffeescript.org/#fat-arrow
- Lexical scoping on StackOverflow - http://stackoverflow.com/questions/1047454/what-is-lexical-scope
- Scope article at Wikipedia - http://en.wikipedia.org/wiki/Scope_(computer_science)
Further reading
A bit more advanced, but an interesting read nevertheless
- https://github.com/raganwald/homoiconic/blob/master/2012/09/lexical-scope-in-coffeescript.md
- https://github.com/raganwald/homoiconic/tree/master/2012/09
And a great book on the subject, by the same author
- https://leanpub.com/coffeescript-ristretto/read (free to read, please consider supporting the author if you find it interesting)