Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Scope for self-referencing functions #1188

TrevorBurnham opened this Issue · 5 comments

4 participants


Someone posted a StackOverflow question this morning that pointed out that

init = ->
  init = -> doSomethingElse()

compiles to

var init;
init = function() {
  var init;
  return init = function() {

That inner var init; declaration surprised him, and it surprises me as well. It's a weird exception to normal scoping rules, isn't it? And as a practical matter, enabling functions to overwrite themselves is quite useful.

The workaround is simple, of course: Just add init = null before the code.


Yep, that's how our scoping works. We don't pay attention to variable declaration hoisting rules. Since init had not yet been defined at that point, it enters the scope inside the function as well. This is no different than your issue #1121. It's a little weird coming from an experienced JS programmer's background, but after talking with jashkenas about it when #1121 was open, I feel that it's right.


I mean, it isn't really the same as #1121 (though "fixing" that issue would also fix this one). As you say, it's the way JavaScript works:

init = function() {
  // "init" lets this function reference itself

But more importantly, it feels antithetical to CoffeeScript's ethos to allow people to use the same name to refer to two different variables even on the same line:

func = -> func = (-> 'this is weird')

I don't see any problem with making a special case for assignments made on the same line as a function definition to be processed for scoping purposes before the inside of the function is. Is there something I'm overlooking?


I think that suggestion would be even more confusing. At least with the way it is right now, it is very consistent. And how does this differ from #1121? You were asking for variable declaration hoisting. Now you're asking for hoisting only when declaring with an assignment to a function.


var init = function(){ return init; }

is interpreted in JS as

var init;
init = function(){ return init; }

and you would like CoffeeScript to behave the same way (except only in some certain situations, apparently). That's hoisting.


Declaring the variable before compiling RHS would fix it, which is reasonable considering = evaluates the LHS first:

$ coffee -e '[][console.log 1] = console.log 2'
@jashkenas jashkenas was assigned
@jashkenas jashkenas closed this in f3f34e9

@satyr and @TrevorBurnham are right -- this is a bug. I've fixed it in the previous commit by reordering the variable declaration and RHS compilation.

@satyr satyr referenced this issue from a commit in satyr/coco
@satyr satyr addressed jashkenas/coffeescript#1188 4b1e3ff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.