未捕获闭包范围? - 咖啡 [英] Closure Scope not captured? — Coffeescript

查看:114
本文介绍了未捕获闭包范围? - 咖啡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆