Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Edit: This explains it better than I did:<br> <a href="http://bonsaiden.github.com/JavaScript-Garden/#function.this" rel="nofollow">http://bonsaiden.github.com/JavaScript-Garden/#function.this</a></p> <p>Your example gives this output on my machine:</p> <pre><code>waiting undefined undefined waiting undefined undefined </code></pre> <p>First, constructors shouldn't return anything, so remove the <code>return this</code> line. The reason is because <code>new</code> creates the new object and the constructor merely populates it. </p> <p>Inside the constructor, <code>this</code> is bound to the object you're creating and normal variables have local scope as usual. This means you have to say <code>this.timeDelayed</code> etc. 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.</p> <p>With these changes, my output matches yours:</p> <pre><code>waiting 0 10 waiting undefined undefined </code></pre> <p>So now onto your problem.</p> <p><code>setTimeout</code> queues a <em>function</em> 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 (like <code>this.wait</code> does). This plays badly with <code>this</code> because in Javascript, the <code>this</code> keyword asways has dynamic scope, which means the <em>caller</em> gets to pick what it means through something like</p> <pre><code>someobject.foo() </code></pre> <p>or whatever. Inside the call to <code>foo</code>, <code>this</code> is bound to <code>someobject</code>. If we took it out:</p> <pre><code>var foo = someobject.foo foo() </code></pre> <p>inside <code>foo</code>, <code>this</code> would be undefined. To make it work, we'd have to say:</p> <pre><code>foo.call(someobject) </code></pre> <p>This is important because <code>setTimeout</code> doesn't set the value of <code>this</code> when the timeout function runs. Instead, replace your call:</p> <pre><code>setTimeout this.wait, 100 </code></pre> <p>with something like:</p> <pre><code> self = this setTimeout (-&gt; self.wait()), 100 </code></pre> <p>This works because the function no longer calls <code>this</code>, it calls <code>self</code> which is an ordinary variable.</p> <p>Coffeescript includes a few tricks and shortcuts here. First, you can avoid capturing <code>self</code> in a closure by using the fat arrow syntax, which automatically binds <code>this</code> in the function to the current object no matter where it's referenced:</p> <p>Second, you can use @ as a shortcut for <code>this.</code> to write instance variables/methods. Thus, my final code sample looks like:</p> <pre><code>WaitModel = -&gt; @timesDelayed = 0 @maxDelay = 10 WaitModel.prototype = wait: -&gt; console.log 'waiting' console.log @timesDelayed, @maxDelay if @timesDelayed &gt;= @maxDelay console.log 'running' @timesDelayed = 0 else @timesDelayed++ setTimeout (=&gt; @wait()), 100 return new WaitModel().wait() </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload