Javascript CoffeeScript为值中的v生成一个全局变量'v`in',从而在事件中导致错误引用
我有以下咖啡脚本代码:Javascript CoffeeScript为值中的v生成一个全局变量'v`in',从而在事件中导致错误引用,javascript,coffeescript,happening,Javascript,Coffeescript,Happening,我有以下咖啡脚本代码: 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) 不必担心代码到底做了什么,因为我使用
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)
不必担心代码到底做了什么,因为我使用的是API of Accounting(一个新的对话应用程序,用户可以在CoffeeScript中制作插件),正因为如此,你无论如何都不会理解它
不过,我会解释:
是长度为10的数组,其中包含对象。这些对象包含诸如日期
、id
、day
、year
等键出席
- 我循环所有日期,并在屏幕上呈现所谓的“部分”
- 每个部分都包含几个div(为了简单起见,在上面的示例中只有一个div)
- 上面的div包含一些文本。”当用户参加活动时为“Y”,当用户不参加活动时为“N”
- 当用户点击此div上的('onTap'-event)时,它将更新本地和共享存储(在上面的示例中,它将只添加一些文本以进行调试)
date
-对象包含正确的数据
问题
我遇到的问题是当我用onTap事件点击div时。当我点击它时,它将始终使用渲染的最后一个日期。假设我有日期01-12-14
到10-12-14
。我点击05-12-14
,它会在屏幕上添加10-12-14的id作为文本。经过长时间的折磨和咒骂,我发现了原因,但我不知道如何解决它
请参阅JavaScript的第一行(第二个代码示例)。如您所见,它正在声明一个全局变量date
。一切都很好,但当我单击某个对象时,它将引用date
,但由于date
在循环的最后一次迭代中已更新,因此它将始终使用该id
所以。如何确保date
在每次迭代循环中保持私有,并确保它在事件中使用正确的值
注
对于k,日期中的v也不起作用,因为它使k
也是全局的。因此,简单地使用日期[k].id
是行不通的。它不是声明一个全局的,只是声明一个全局的代码。如果它在一个函数中,它就不会是一个全局函数
这个问题与全局无关。这是因为闭包是如何工作的。闭包对它们关闭的变量有持久的引用,而不是创建闭包时它们的值的副本。因此,为onTap
处理程序创建的所有函数都使用相同的单个date
对象
为了防止这种情况发生,给他们每个人一些自己的东西,让他们在不改变的情况下关闭。如果dates
是一个数组,请使用forEach
(对于那些熟悉CoffeeScript但没有发生的人,请注意:->
前面的!
不是通常的!
运算符。发生扩展了CoffeeScript,因此使用!->
而不是->
声明函数,而不会生成CoffeeScript通常具有的隐式返回值。)。[感谢您指出这一点。]
因此:
…这就变成了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
上关闭,该参数不变
dates.forEach (date) !->
Dom.section !->
Dom.div !->
Dom.text if date.attending then 'Y' else 'N'
Dom.onTap !->
Dom.text date.id
dates.forEach(function(date) {
Dom.section(function() {
Dom.div(function() {
Dom.text(date.attending ? 'Y' : 'N');
Dom.onTap(function() {
Dom.text(date.id);
});
});
});
});