封闭范围不被捕获? – 咖啡

好的,我不知道如何为这个问题标题。

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" 

我明白,variablesitemBox是在openDir的范围下定义的。 但是由于指出的行是在一个lambda函数中,不应该itemBox那里捕获由父范围的itemBox引用的对象,而不是突变到它所引用的最后一个对象?

说清楚,我期望每个itemBox的点击处理程序执行自己的addClass "selected" 。 但是会发生什么情况是每个点击处理程序中的itemBox总是引用最后一个itemBox。

我可以通过更改itemBox被声明的位置来轻松解决这个问题。 即改变

 for item in data.contents 

 data.contents.forEach (item) -> 

但我想知道为什么lambda函数不捕获variables当前值。

这个循环:

 for item in data.contents itemBox = $ "<div/>", class: "itembox" 

如果你不习惯(咖啡| Java)脚本范围有点欺骗性。 范围确实看起来更像这样:

 itemBox = undefined for item in data.contents itemBox = $ "<div/>", class: "itembox" 

所以只有一个itemBoxvariables,并且该循环的每次迭代都使用相同的variables。 点击处理程序保持对itemBox的引用,但不会计算该variables,直到调用click处理程序,以便所有处理程序以相同的itemBox值结束,并且将作为循环结束处的itemBox值。

从精美的手册 :

当使用JavaScript循环来生成函数时,通常会插入一个闭包封装,以确保循环variables被closures,所有生成的函数不会共享最终值。 CoffeeScript提供了do关键字,它立即调用传递函数,转发任何参数。

所以你可以这样做:

 for item in data.contents do (item) -> # As before... 

让你的itemBox作用域到每个循环迭代。

使用forEach

 data.contents.forEach (item) -> 

而不是一个简单的循环工作,因为你有效地使用一个函数作为循环的主体,该函数内的任何variables将作用于该函数。

Interesting Posts