我有以下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的数组,其中包含对象。这些对象包含id
,day
,year
,attending
之类的键。我遍历所有日期,并在屏幕上的“部分”中呈现这些日期。
每个部分包含几个div(为简单起见,在上面的示例中只有一个)。
上面的div包含一些文本。用户正在参加活动时为“ Y”,否则则为“ N”。
当用户在该div上点击(“ onTap”事件)时,它将更新本地存储和共享存储(在上面的示例中,它将仅添加一些用于调试的文本)。
一切正常,它在正确的部分显示了正确的日期和参加者人数。因此,
date
对象包含正确的数据。问题
我遇到的问题是当我使用onTap事件点击div时。当我点击它时,它将始终使用显示的最后日期。假设我有
01-12-14
到10-12-14
的日期。我点击05-12-14
,它将在屏幕上添加ID 10-12-14作为文本。经过长时间的折腾和诅咒,我发现了造成这种情况的原因,但我不知道如何解决。请参阅JavaScript的第一行(第二个代码示例)。如您所见,它声明了一个全局变量
date
。一切都可以正常显示,但是当我单击某些内容时,它将引用date
,但是由于date
在循环的最后一次迭代中已更新,因此它将始终使用该id。所以。如何确保
date
在每个迭代循环中保持私有,并确保在事件中使用正确的值?注意
for k, v in dates
也不起作用,因为它也使k
全局化。因此,简单地使用dates[k].id
是行不通的。 最佳答案
它不是在声明全局变量,而只是声明该代码的全局变量。如果它在一个函数中,那将不是全局的。
该问题与全局变量无关。这是因为闭包是如何工作的。闭包对它们关闭的变量有持久的引用,而不是创建闭包时值的副本。因此,您为onTap
处理程序创建的所有函数都使用相同的单个date
对象。
为了防止这种情况,请给他们每个人自己的东西以使其关闭。如果dates
是数组,请使用forEach
。
(请注意那些不熟悉CoffeeScript但不熟悉的人:!
前面的->
不是通常的!
运算符。对幸福的理解是对CoffeeScript的扩展,使得使用!->
而不是->
声明函数,则不会生成Coffeescript通常具有的隐式返回值。(感谢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
回调的每次迭代创建的闭包将覆盖该回调迭代的参数date
,该参数不变。