问题
I have a for loop iterating through a variable number of draggable elements, creating a stop-event callback for each. The callback function needs to know the index of the item that it is linked to.
I've encountered what I think is a closure problem: when the callbacks are fired off, the state of the loop iterator index variable that gets passed to the callback (_x) is the last value of the loop iterator index, rather than the value of that iterator index at the time the callback function was defined. Some coffeescript below:
for _x in [0..total]
$(window).ready $(".draggable-#{_x}").draggable
cursor: 'move'
handle: ".draggable-image-move-button-#{_x}"
containment: 'div#banner-builder-preview'
stop: =>
alert "x === #{_x}"
In the example above, the alert prompt will always print "x === total+1" rather than "x === 0", "x === 1"... etc.
What's the best solution to pass a unique index to the callback for each of the elements that have a stop event? I would prefer to do this without resorting to yet another jquery selector to pull more data from whatever element fired off the callback.
UPDATE:
Another problem I'm now running into: my callback, within the for loop, cannot see other functions defined in the file. I think that's very odd, even if the definition happens before the for loop is used to create the anonymous callback functions.
For example:
for _x in [0..total]
do (_x) ->
$(window).ready $(".draggable-#{_x}").draggable
cursor: 'move'
handle: ".draggable-image-move-button-#{_x}"
containment: 'div#banner-builder-preview'
stop: =>
someFunction _x # ... this line throws an exception, not defined
alert "x === #{_x}
回答1:
The problem is that your callbacks:
stop: =>
alert "x === #{_x}"
all end up referencing _x but they don't evaluate _x until they get called. By the time that happens, _x has the value total + 1. This is such a common issue that CoffeeScript has the do keyword to help:
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
dokeyword, which immediately invokes a passed function, forwarding any arguments.
So you can say this instead:
for _x in [0..total]
do (_x) ->
$(window).ready $(".draggable-#{_x}").draggable
#... as before
来源:https://stackoverflow.com/questions/17798003/creating-jquery-draggable-stop-callbacks-in-a-for-loop