Closure Scope not captured? — Coffeescript
Solution 1:
This loop:
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
is somewhat deceptive if you're not used to (Coffee|Java)Script scope. The scoping actually looks more like this:
itemBox = undefined
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
so there is only one itemBox
variable and that same variable gets used by each iteration of the loop. The click handler keeps a reference to itemBox
but doesn't evaluate the variable until the click handler is called so all the handlers end up with the same itemBox
value and that will be the itemBox
value at the end of the loop.
From the fine manual:
When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the
do
keyword, which immediately invokes a passed function, forwarding any arguments.
So you could do this:
for item in data.contents
do (item) ->
# As before...
to get your itemBox
scoped to each iteration of the loop individually.
Using forEach
:
data.contents.forEach (item) ->
instead of a simple loop works because you're effectively using a function as the loop's body and any variables inside that function will be scoped to that function.