未捕获关闭范围?— 咖啡脚本 [英] Closure Scope not captured? — Coffeescript

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

问题描述

好的,我不知道如何表达这个问题的标题.

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 的点击处理程序对自己执行 addClass "selected".但是发生的情况是,每个点击处理程序中的 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 的声明位置来轻松解决此问题.即改变

I can easily fix this by changing where itemBox gets declared. i.e. changing

for item in data.contents

进入

data.contents.forEach (item) ->

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

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"

如果您不习惯 (Coffee|Java)Script 范围,

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

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 分别限定为循环的每个迭代.

to get your itemBox scoped to each iteration of the loop individually.

使用 forEach:

data.contents.forEach (item) ->

而不是简单的循环起作用,因为您有效地将函数用作循环的主体,并且该函数内的任何变量都将作用于该函数.

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天全站免登陆