javascript - CoffeeScript 在 `v` 中创建一个 `for v in values` 的全局变量,导致事件引用错误

标签 javascript coffeescript happening

我有以下 CoffeeScript 代码:

for date of dates
    Dom.section !->
        Dom.div !->
            Dom.text if date.attending then 'Y' else 'N'
            Dom.onTap !->
                Dom.text date.id

转换为以下 JavaScript(根据 coffeescript.org)

var date;

for (date in dates) {
  Dom.section(!function() {
    return Dom.div(!function() {
      Dom.text(date.attending ? 'Y' : 'N');
      return Dom.onTap(!function() {
        return Dom.text(date.id);
      });
    });
  });
}

不要理会代码到底做了什么,因为我正在使用 Happening 的 API(一个新的对话应用程序,使用它可以在 CoffeeScript 中制作插件),正因为如此,你无论如何都不会理解它。

不过我会解释一下:

  • dates 是一个长度为 10 的数组,其中包含对象。这些对象包含 iddayyearattending 等键。
  • 我遍历所有日期并将它们呈现在屏幕上所谓的“部分”中。
  • 每个部分都包含多个 div(为简单起见,在上面的示例中只有一个)。
  • 上面的 div 包含一些文本。用户参加事件时为“Y”,未参加事件时为“N”。
  • 当用户在这个 div 上点击('onTap'-event)时,它会更新本地和共享存储(在上面的示例中它只会添加一些用于调试的文本)。

一切正常,它在正确的部分显示了正确的日期和与会者数量。所以 date 对象包含正确的数据。

问题

我遇到的问题是当我使用 onTap 事件点击 div 时。当我点击它时,它将始终使用呈现的最后日期。假设我有日期 01-12-1410-12-14。我点击 05-12-14,它会在屏幕上添加 id 10-12-14 作为文本。经过长时间的头痛和诅咒后,我找到了造成这种情况的原因,但我不知道如何解决。

请参阅 JavaScript 的第一行(第二个代码示例)。如您所见,它正在声明一个全局变量 date。一切都很好,但当我点击某些东西时,它会引用 date,但由于 date 已在循环的最后一次迭代中更新,它将始终使用那个编号。

所以。我如何确保 date 在每个迭代循环中保持私有(private)并确保它在事件中使用正确的值?

注意事项

for k, v in dates 也不起作用,因为它也使 k 成为全局变量。所以简单地使用 dates[k].id 是行不通的。

最佳答案

它没有声明全局,只是声明了该代码的全局内容。如果它在一个函数内,它就不会是全局的。

问题与全局变量无关。这是因为闭包是如何工作的。闭包对它们关闭的变量有一个持久引用,而不是它们在创建闭包时的值的副本。因此,您为 onTap 处理程序创建的所有函数都使用相同的单个 date 对象。

为防止这种情况发生,给他们每个人一些他们自己的东西来关闭那些不会改变的东西。如果 dates 是数组,请使用 forEach

(熟悉 CoffeeScript 但不熟悉 Happening 的人请注意:-> 前面的 ! 不是通常的 ! 运算符. Happening extends CoffeeScript 这样一个函数是使用 !-> 而不是 -> 声明的,Coffeescript 通常具有的隐式返回值不会生成。[With thanks到 Erik Dolor 指出这一点。])

所以:

dates.forEach (date) !->
    Dom.section !->
        Dom.div !->
            Dom.text if date.attending then 'Y' else 'N'
            Dom.onTap !->
                Dom.text date.id

...变成这个 JavaScript:

dates.forEach(function(date) {
  Dom.section(function() {
    Dom.div(function() {
      Dom.text(date.attending ? 'Y' : 'N');
      Dom.onTap(function() {
        Dom.text(date.id);
      });
    });
  });
});

现在,为 forEach 回调的每次迭代创建的闭包在该回调迭代的argument date 上关闭,这不会改变。

关于javascript - CoffeeScript 在 `v` 中创建一个 `for v in values` 的全局变量,导致事件引用错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27621543/

相关文章:

javascript - CORS + Cordova : issues with : Access-Control-Allow-Origin

javascript - 更改类时超出最大调用堆栈大小 - Bootstrap、jQuery

javascript - jQuery 验证 contenteditable span 或 div 的自定义消息

javascript - 未知提供者 : tProvider <- t

javascript - Angular - 检查数据是否存在?

ruby-on-rails - Rails Assets 管道不指示哪个文件产生了错误

error-handling - ActionBar问题

javascript - 实时文本突出显示