Gau*_*han 5 scope coffeescript
好的,我不知道如何用这个问题来标题.
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"
Run Code Online (Sandbox Code Playgroud)
我知道变量itemBox是在openDir这里的范围下定义的.但是由于指出的行是lambda函数,不应该itemBox捕获itemBox父作用域引用的对象而不是变异到它引用的最后一个对象吗?
说清楚,我希望每个的click处理程序能够自行itemBox执行addClass "selected".但是,itemBox在每个点击处理程序中总是引用最后一个itemBox.
我可以通过更改itemBox声明的位置来轻松解决此问题.即改变
for item in data.contents
Run Code Online (Sandbox Code Playgroud)
成
data.contents.forEach (item) ->
Run Code Online (Sandbox Code Playgroud)
但我想知道为什么lambda函数不捕获变量当前值.
这个循环:
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
Run Code Online (Sandbox Code Playgroud)
如果您不习惯(Coffee | Java)脚本范围,则有点欺骗性.范围实际上看起来更像是这样的:
itemBox = undefined
for item in data.contents
itemBox = $ "<div/>", class: "itembox"
Run Code Online (Sandbox Code Playgroud)
所以只有一个itemBox变量,并且循环的每次迭代都会使用相同的变量.在itemBox调用单击处理程序之前,单击处理程序保留对引用的引用但不评估该变量,因此所有处理程序最终都具有相同的itemBox值,并且将是itemBox循环结束时的值.
从精细手册:
当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不仅仅共享最终值.CoffeeScript提供
do关键字,该关键字立即调用传递的函数,转发任何参数.
所以你可以这样做:
for item in data.contents
do (item) ->
# As before...
Run Code Online (Sandbox Code Playgroud)
让你的itemBox范围单独循环到循环的每个迭代.
使用forEach:
data.contents.forEach (item) ->
Run Code Online (Sandbox Code Playgroud)
而不是一个简单的循环工作,因为你有效地使用一个函数作为循环的主体,该函数内的任何变量将作用于该函数.
| 归档时间: |
|
| 查看次数: |
901 次 |
| 最近记录: |