It's a plain mistake by the tutorial author. @
in CoffeeScript always compiles to this
in JavaScript, and followed by an identifier such as @restauranteur
, it's this.restauranteur
.
Inside a class or a function that will be bound to an object (we could call that a method), it makes a lot of sense since we're expecting the this
object to have a restauranteur
property. However, in the top scope of a file, which is how he uses it in your example, it makes no sense. It's also a very bad idea; let's see what this compiles to:
@restauranteur.controller 'HomeCtrl', ['$scope', ($scope) ->
# Notice how this controller body is empty
]
As a .coffee file of its own, this gets us:
(function() {
this.restauranteur.controller('HomeCtrl', ['$scope', function($scope) {}]);
}).call(this);
To be clear, that a function that's invocated as soon as it's defined is the module pattern (read more about it here).
Referencing this
in a function that's not bound to a specific object will reference the global scope, window
in the case of browsers. That means that you'll be able to do restauranteur
from anywhere in your code, even in dependencies, other modules, etc. It's exactly the opposite that the module pattern looks for! It's completely unnecessary and you can remove it from everywhere that's not a class/method definition.
What the tutorial author is doing is also defining @restauranteur
, thus window.restauranteur
as a module in a different file (main.js.coffee):
@restauranteur = angular.module('restauranteur', [])
That's the only reason it works. However, he should've done it this way to not pollute the global namespace:
main.js.coffee
restauranteur = angular.module('restauranteur', [])
restauranteur.config(['$routeProvider', ($routeProvider) ->
[...]
Actually, the definition of restauranteur as a variable is useless since he uses its value only once in the file. It might help readability, though.
HomeCtrl.js.coffee
angular.module('restauranteur').controller 'HomeCtrl', ['$scope', ($scope) ->
# Notice how this controller body is empty
]
By contrast, using @
is useful here:
describe Restaurant do
before do
@restaurant = Restaurant.new(name: "Momofuku")
end
[...]
Here, restaurant
will be part of the this
object that's accessible from every test, so you can use it like this:
describe "when name is not present" do
before { @restaurant.name = " " }
it { should_not be_valid }
end
because this
is the same in both cases, and not just because it's the global scope. Let's see a simpler example:
class Restaurant
isOpen = false
open: ->
@isOpen = yes
close: ->
@isOpen = no
In this case, isOpen
will be an instance field of Restaurant
instances, since this
will be the instance for which the method was called, for example like this:
myRestaurant = new Restaurant
myRestaurant.open()
I hope that was clear enough. I suggest you read through the CoffeeScript homepage from top to bottom, it's pretty short and straightforward. Also, please be sure to have a good JavaScript background before attempting to use CoffeeScript for real projects, it will save you a couple of headaches.