Problem
Hi people, I'm reasonably new to JavaScript and I come from the very object-oriented world of Python and Java, that's my disclaimer.
There are two chunks of code below, alternative implementations, one in JavaScript, one in Coffeescript. I am trying to run them on the server in a Meteor.js application. The problem I am experiencing is when calling the function "setInterval" using the bound-method "this.printSomething" as my callback, once that callback is executed, it loses scope with the instance resulting in "this.bar" being undefined! Can anyone explain to me why either the JavaScript or the coffescript code isn't working?
JavaScript Implementation
function Foo(bar) {
this.bar = bar;
this.start = function () {
setInterval(this.printSomething, 3000);
}
this.printSomething = function() {
console.log(this.bar);
}
}
f = new Foo(5);
f.start();
Coffeescript Implementation
class foo
constructor: (bar) ->
@bar = bar
start: () ->
Meteor.setInterval(@printSomething, 3000)
printSomething: () ->
console.log @bar
x = new foo 0
x.start()
You could also try creating a closure to capture the
this
. Like this:When you enter a function, you get a new scope in javascript. You can inherit from the parent scope, but the value of
this
changes. In coffeescript, you can use the fat arrow (which looks like it is going to be part of ecmascript 6) which basically retains a reference tothis
before going into the new scope.The standard way to handle this kind of thing in javascript is to create a reference to
this
at the point you want to refer to, and then use the reference in your out of scope calls...You lose your context of
Foo
in the setInterval callback. You can use Function.bind to set the context to something like this to set the context for the callback function reference back toFoo
instance.With the call
The callback method gets the global context (window in case of web or global in case of tenants like node) so you don't get property
bar
there sincethis
refers to the global context.Fiddle
or just