CoffeeScript's Scoping is Madness
It ends up CoffeeScript's scoping of variables is basically nonexistent. As soon as you use a variable named
x for example in an outer scope,
x becomes global across all the inner scopes. This to me is a huge issue. Defining a variable in your code should never redefine the definition of inner functions. This is madness. This is CoffeeScript
Look at the following examples:
All fine and good, but let's make one small change and define a variable named
y in the outer scope, outside the function.
Notice the highlighting indicating the scope of the
y variable. By defining
y in the global scope all subsequent
y's become global, forever. You cannot have a variable named
y and the outer
y could and would be separate. CoffeeScript though does not allow Shadowing or defining a variable named the same thing in a deeper scope.
var keyword defines the scope of a variable. Leave it out and it scopes downward until it hits a
var definition of that variable or the global level. This means that deeper scopes inherits from a level above unless it defines its own scope of the variable. CoffeeScript on the other hand offers you no method to scope a variable. Scoping is entirely automatic, and the lowest level use of a variable name is the single instance of it.
This is an extremely dangerous behavior. You need to be aware of every variable named blah within the current scope as well as every single deeper scope before defining a blah variable within your code, or else latter definitions will be trampled by your new earlier definition.
To better explain the problem, let's say you have four functions all using a generic
i variable. Now if we use an
i for a loop outside of your functions suddenly the definition of all four of your functions changes. They all reference the global
i rather than the four local
i's they were a moment ago.
This means the only "safe" way to write CoffeeScript is to assume all variables are global, because essentially they are.
There are proposed solutions, such as a Go-lang style
:= for inner scoping, but these have not been accepted as of this writing. The creator of CoffeeScript, Jeremy Ashkenas, when questioned about it by Armin Ronacher on Twitter replied:
Not gonna happen ;) Forbidding shadowing altogether is a huge win, and a huge conceptual simplification.
It is a bad behavior, period.
I'd like to also suggest reading Armin Ronacher's The Problem with Implicit Scoping in CoffeeScript. It eloquently describes the problem from a slightly different angle.
- I've started a mass argument on reddit here.
- I've pissed off Reginald Braithwaite, the author of CoffeeScript Ristretto, so badly he's giving away 100 copies of his book for free!
- I've been upgraded to Not Wrong™ by the author!