未捕获闭包范围? - 咖啡 [英] Closure Scope not captured? — Coffeescript
问题描述
好的,我不知道如何用这个问题来标题。
Okay, I don't know how to phrase the title for this question.
openDir = (path) ->
socket.emit "get_metadata", path, (data) ->
columnBox = $ "<div/>", class: "columnbox"
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
itemBox.click ->
columnBox_inner.children().removeClass "selected"
itemBox.addClass "selected" # <<<--- Over here
openDir item.path
columnBox.append itemBox
columnBox.appendTo "#columnscontainer"
我理解变量 itemBox
在 openDir
的范围内定义。但由于指出的行在lambda函数中,应该不会 itemBox
捕获 itemBox
引用的对象父类范围,而不是变得被引用的最后一个对象?
I understand that the variable itemBox
is defined under openDir
's scope here. But since the pointed out line is in a lambda function, shouldn't itemBox
there capture the object referenced by itemBox
of the parent scope instead of getting mutated to the last object referenced by it?
为了清楚,我希望每个 itemBox
向自己执行 addClassselected
。但是会发生什么呢,在每个点击处理程序中的 itemBox
总是引用最后一个itemBox。
To put it clearly, I expect the click handler of each itemBox
to perform addClass "selected"
to itself. But what happens is that itemBox
in each of the click handlers always refer to the last itemBox.
通过更改itemBox被声明的位置来解决这个问题。即更改data.contents中的项目
I can easily fix this by changing where itemBox gets declared. i.e. changing
for item in data.contents
到
data.contents.forEach (item) ->
但我想知道为什么lambda函数不捕获变量当前值。 p>
But I'd like to know why the lambda function does not capture the variables current value.
推荐答案
此循环:
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
b $ b
有点欺骗,如果你不习惯(Coffee | Java)脚本作用域。范围实际上看起来更像这样:
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"
itemBox
变量,并且该循环的每次迭代使用相同的变量。点击处理程序保留对 itemBox
的引用,但是不调用该变量,直到调用点击处理程序,所以所有处理程序都以相同的 itemBox
值,这将是循环结束时的 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.
从精细手动:
使用一个JavaScript循环来生成函数,通常插入一个闭包,以确保循环变量被关闭,所有生成的函数不只是共享最终值。 CoffeeScript提供了
do
关键字,它立即调用传递的函数,转发任何参数。
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.
所以你可以这样做:
for item in data.contents
do (item) ->
# As before...
获得 itemBox
使用 forEach
:
data.contents.forEach (item) ->
而不是一个简单的循环,因为你有效地使用一个函数作为循环的body和任何变量里面的函数将作用于该函数。
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.
这篇关于未捕获闭包范围? - 咖啡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!