[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