我使用CoffeScript创建了一些Javascript对象。这些对象之一是实验对象:
class Experiment
@clock
@events
constructor: (@params) ->
@events = new EventsTable
@clock = 0
run: ->
setInterval ->
perform_routine
, 1000
perform_routine: ->
events = @events.get(@clock)
for event in events
if event['action'] == 'start'
console.log('an event starts.')
else
console.log('an event has been finished.')
console.log(@clock)
@clock++
每次用户单击某个按钮时,都必须创建一个实验。考虑到这一点,我实现了一个jQuery触发器:
$ ->
$('#start-simulation').click (event) ->
event.preventDefault();
params = {}
$('#simulation-parameters').find('input').each ->
params[$(this).attr('name')] = $(this).val();
simulation = new Experiment params
simulation.run();
问题是我总是收到Uncaught ReferenceError:未定义实验
由于进行了一些研究,我还尝试使用@定义类名称,但是这样做时,使用类内部的方法会出现很多错误。
考虑到我以正确的顺序导入了所有必要的文件(第一次实验,然后是带有jQuery函数的实验),这种行为对我来说似乎是完全不自然的,但这可能是由于我缺乏JavaScript经验。
您知道在jQuery中使用JS外部对象的正确方法是什么吗?
最佳答案
您有几个问题:
CoffeeScript将代码包装在SIF中,以防止范围爬行。这个:
class C
变成这样的东西:
(function() {
var C = // the JavaScript definition of C ...
}).call(this);
SIF包装器可以防止CoffeeScript中的任何内容意外污染全局名称空间。在您的情况下,
Experiment
JavaScript变量隐藏在函数内部,因此在任何其他CoffeeScript文件中都不可见。通常的浏览器解决方案是说
class @Experiment
使您的类成为全局对象的属性。更好的解决方案是手动命名事物。在发生其他任何事情之前,您想说:window.app = { } # where "app" is some namespace unique to your application
然后您可以说
class app.Experiment
和new app.Experiment
。在
class
级别,@
是类本身。这意味着:class Experiment
@clock
@events
声明了两个类属性(
Experiment.clock
和Experiment.events
),但忽略了为其赋予一个值。这些属性不在原型中,而是在类函数本身上。您可能想说:class Experiment
clock: undefined
events: undefined
如果您的目的是告诉外界
Experiment
实例具有clock
和events
属性。在CoffeeScript中,说
f
不会调用函数f
,它只是为您提供对f
的引用,而无需费心将其存储在任何地方。要调用不带参数的函数,请说f()
。另外,如果要调用方法,则需要提供接收器。就您而言,您的constructor
应该更像这样:constructor: (@params) ->
@events = new EventsTable
@clock = 0
@create_cells()
@create_calls()
您的
run
方法遭受与constructor
相同的“缺少接收者并且缺少函数调用括号”的问题。另外,当setInterval
调用其回调时,它不提供任何特定的@
(又名this
),因此您需要一个绑定函数:run: -> setInterval (=> @perform_routine()), 1000
# or
run: -> setInterval @perform_routine.bind(@), 1000
# or:
perform_routine: => ...
run: -> setInterval @perform_routine, 1000
您可能也想将
setInterval
返回值存储在某个地方,这样您可以调用clearInterval
停止它:run: ->
@interval = setInterval ...
stop: ->
clearInterval(@interval) if(@interval)
@interval = undefined
您的
Experiment
其余部分中可能也有类似的问题。