I have the following code:
WaitModel = ->
timesDelayed = 0
maxDelay = 10
return this
WaitModel.prototype =
wait: ->
console.log 'waiting'
console.log this.timesDelayed, this.maxDelay
if this.timesDelayed >= this.maxDelay
console.log 'running'
this.timesDelayed = 0
else
this.timesDelayed++
setTimeout this.wait, 1000
return
new WaitModel().wait()
I think this should produce output like:
waiting
0 10
waiting
1 10
...
But instead it produces output like:
waiting
0 10
waiting
undefined undefined
Where am I unsetting this.timesDelayed and this.maxDelay? Am I misunderstanding the way to make objects here?
Edit: This explains it better than I did:
http://bonsaiden.github.com/JavaScript-Garden/#function.this
Your example gives this output on my machine:
First, constructors shouldn’t return anything, so remove the
return thisline. The reason is becausenewcreates the new object and the constructor merely populates it.Inside the constructor,
thisis bound to the object you’re creating and normal variables have local scope as usual. This means you have to saythis.timeDelayedetc. in the constructor — else your two variables will fall out of scope when the constructor exits and won’t show up as fields or anything later.With these changes, my output matches yours:
So now onto your problem.
setTimeoutqueues a function to run. Functions are just functions — they don’t carry extra information about which object they apply to, even if you treat them as methods (likethis.waitdoes). This plays badly withthisbecause in Javascript, thethiskeyword asways has dynamic scope, which means the caller gets to pick what it means through something likeor whatever. Inside the call to
foo,thisis bound tosomeobject. If we took it out:inside
foo,thiswould be undefined. To make it work, we’d have to say:This is important because
setTimeoutdoesn’t set the value ofthiswhen the timeout function runs. Instead, replace your call:with something like:
This works because the function no longer calls
this, it callsselfwhich is an ordinary variable.Coffeescript includes a few tricks and shortcuts here. First, you can avoid capturing
selfin a closure by using the fat arrow syntax, which automatically bindsthisin the function to the current object no matter where it’s referenced:Second, you can use @ as a shortcut for
this.to write instance variables/methods. Thus, my final code sample looks like: