Links

Lists

Latest Updates

Ruby On Rails List
Python list
Advanced Java
The JavaScript List
Apache Users
Full Disclosure
Linux Security

Search the archives!


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Javascript] Javascript Objects and Scope


  • From: jeffreyag at earthlink.net (Jeff Greenberg)
  • Subject: [Javascript] Javascript Objects and Scope
  • Date: Sat Nov 19 00:08:11 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?
>