[Javascript] Javascript Objects and Scope
Jeff Greenberg
jeffreyag at earthlink.net
Sat Nov 19 00:08:06 CST 2005
The "this" keyword in Javascript is special... it always refers to the
current scope, that is, the scope in which it is being evaluated "right
now." In your case, the "this" inside the anonymous function you've
defined in the call to setInterval refers to the global scope (window)
because setInterval is always evaluated in this scope. When you call
setInterval, the Javascript interpreter saves the code for later, then
goes ahead and evaluates it in the global scope after the delay is over,
so "this" refers to the window's scope.
There are a few ways to deal with this when using setInterval. The
simplest is, of course, to call the object explicitly by name
("foo.increment()"), but that obviously won't help in most situations.
An elegant solution for this is something you've already inadvertently
done, which is to use a closure. If you're not familiar with closures,
do a google search for "javascript closures". The long and short of it
is that inner functions, or functions defined within other functions,
capture any variables in the scope of their parent.
In this case, when you call foo.test, and it creates the interval, you
can capture the proper "this" by assigning it to a variable, like so:
this.test=function() {
var self=this;
interval=setInterval(function() {
if (test)
self.increment();
else clearInterval(interval);
},400);
}
Now, even though the setInterval is evaluated in the global scope, the
anonymous function you've created inside the call to setInterval will
capture the variable "self" which referred to the proper "this" when it
was created.
Your code to clear the interval will work for the same reason, because
you close over the "interval" variable as well, though you should use
the "var" keyword to define it ("var interval=") unless you want to
share that variable between all instances of objects created from your
customClass. "var" makes a variable private to an object, while defining
a variable without it in an object makes that variable shared across
object instances.
The only thing to be aware of when using closures is that in some cases
(especially in Internet Explorer) they can cause memory leaks when
closing over references to DOM objects. Again, if you search for
"javascript closures", you will find several articles about this.
Hope that helps.
Ryan Cannon wrote:
> Hi folks,
>
> I'm just starting with Javascript objects, and I'm having variable
> scope issue that I can't seem to resolve. The following works:
>
> function customClass() {
> this.myFunc=function() {
> // do something
> }
> }
> window.onload=function() {
> var foo=new customClass();
> foo.test=function() {
> interval=setInterval(function() {
> if (test)
> foo.increment();
> else clearInterval(interval);
> }, 400);
> }
> foo.test();
> }
>
> Trying to move the interval inside the object, however, fails:
>
> function customClass() {
> this.myFunc=function() {
> // do something
> }
> this.test=function() {
> interval=setInterval(function() {
> if (test)
> this.increment();
> else clearInterval(interval);
> },400);
> }
> }
> window.onload=function() {
> var foo=new customClass();
> foo.test();
> }
>
> I have a feeling this is a scope problem, because javascript doesn't
> throw an error. Any ideas?
>
More information about the Javascript
mailing list