Shadowing variables in CoffeeScript

CoffeeScript is a meta-language which compiles directly into JavaScript, has some neat features and patterns baked in, and is a favorite of many JavaScript hackers, and I’ve been playing around with it in the last few days.

For the most part, I like it, but it steps on one of the most useful features of JavaScript – the var keyword for scope specification. From the manual:

The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.

This behavior is effectively identical to Ruby’s scope for local variables. Because you don’t have direct access to the var keyword, it’s impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you’re not reusing the name of an external variable accidentally, if you’re writing a deeply nested function.

Be careful that you’re not reusing the name of an external variable? This is supposed to make your life easier, not harder!

Thankfully, there’s a quick and simple way around it – just stick your var declarations in backticks.

outer = 1
changeNumbers = ->
  `var outer`
  inner = -1
  outer = 10
inner = changeNumbers()

This results in outer === 1 && inner === 10 as expected. This isn’t perfect – CoffeeScript doesn’t notice if you declare a variable that it can’t find in an outer scope, so you can end up with two var foo statements in your compiled code – but at least it’s possible.

You also still get shadowing when defining a function’s argument names:

outer = 1
changeNumbers = (outer) ->
  inner = -1
  outer = 10
inner = changeNumbers(42)

It’s too bad that some of the CoffeeScript variants don’t have anything like the same degree of traction as CoffeeScript does, or I might think strongly about trying LiveScript, a second-generation offshoot of CoffeeScript that includes a non-declaring assignment operator, :=, to avoid the backtick hackery.

2 Responses