Nodejs + Coffeescript 的变量范围
Posted
技术标签:
【中文标题】Nodejs + Coffeescript 的变量范围【英文标题】:Variable scope with Nodejs + Coffeescript 【发布时间】:2014-08-29 18:48:38 【问题描述】:我很难找到这个。
...
for offset in [1..3]
queryDate = moment().subtract(offset, 'days')
console.log offset # gives 1, 2, 3
# check if a row already exists for this day
Datum.findOne date: $lte: queryDate.toDate() , (err, datum) ->
console.log offset # gives 4, 4, 4
...
确定变量范围以便它们可以在回调中使用的正确方法是什么?
【问题讨论】:
【参考方案1】:使用包装函数应该可以工作。
# this is a wrapper to setTimeout
# it's used as a substitute to Datum.findOne in the question
delay = (ms, func) -> setTimeout func, ms
myRange = 4
myWrapper = (offset, range) -> # range could be queryDate
delay 0, -> # delay could be Datum.findOne
console.log offset + ' ' + range
for offset in [1..myRange]
myWrapper offset, myRange
delay 是 setTimeout 的别名(某种),建议 here
【讨论】:
您能否简要解释一下超时/延迟的必要性?消除延迟会产生相同的输出,并且程序会立即完成。 delay (setTimeout) 只是 Datum.findOne 的替代品,我放在那里是为了测试一个带有回调的简单函数,实际上不需要延迟,如果造成混淆,请见谅【参考方案2】:这实际上是一个闭包问题而不是范围问题。发生的情况是,当您在 javascript 中定义一个函数时(当然也是 coffeescript),该函数会记住创建它的上下文,包括父作用域中的所有变量。但是所拥有的不是变量的副本,而是这些变量的引用。
来自Datum.findOne
的回调将在您的for
循环完成迭代后被调用。这意味着offset
变量已经增加了。你可以很容易地防止它在Datum.findOne
周围包裹一个匿名函数,如下所示:
for offset in [1..3]
do ( offset = offset ) ->
Datum.findOne date: $lte: queryDate.toDate() , (err, datum) ->
console.log offset
将变量作为参数传递给函数将创建它的副本。
我相信在循环内定义函数更便于阅读,但如果函数很大,或者循环有很多迭代,实际上最好在别处定义它。
//edit:其实coffeescript会在循环外定义。
您可能想参考这个question 来了解闭包。
【讨论】:
以上是关于Nodejs + Coffeescript 的变量范围的主要内容,如果未能解决你的问题,请参考以下文章
现在啊还不太清楚 nodejs和coffeescript 的关系
Angular遇上CoffeeScript - NgComponent封装