columnBox = -6ren">
gpt4 book ai didi

scope - 未捕获闭包范围? — CoffeeScript

转载 作者:可可西里 更新时间:2023-11-01 16:42:01 28 4
gpt4 key购买 nike

好吧,我不知道如何表述这个问题的标题。

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 引用的对象,而不是突变为引用的最后一个对象靠它吗?

明确地说,我希望每个 itemBox 的点击处理程序对其自身执行 addClass "selected"。但实际情况是,每个点击处理程序中的 itemBox 始终引用最后一个 itemBox。

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

for item in data.contents

进入

data.contents.forEach (item) ->

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

最佳答案

这个循环:

for item in data.contents
itemBox = $ "<div/>", class: "itembox"
如果您不习惯 (Coffee|Java)Script 作用域,

会有些欺骗性。范围实际上看起来更像这样:

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

因此只有一个 itemBox 变量,并且循环的每次迭代都会使用同一个变量。单击处理程序保留对 itemBox 的引用,但在调用单击处理程序之前不会评估变量,因此所有处理程序最终都具有相同的 itemBox 值,这将是循环结束时的 itemBox 值。

来自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.

所以你可以这样做:

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

让您的 itemBox 单独作用于循环的每个迭代。

使用forEach:

data.contents.forEach (item) ->

而不是一个简单的循环是有效的,因为你有效地使用一个函数作为循环的主体,并且该函数内的任何变量都将被限定为该函数。

关于scope - 未捕获闭包范围? — CoffeeScript ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30971232/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com