Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    VR2
    VR2 is offline
    New Coder
    Join Date
    Jul 2006
    Posts
    39
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Object classes and setTimeoout

    In the example below, why is it that when the dog takes a dump, the "this" property is accessible to all object methods, as you would expect.

    But when the dog Barks, the first time though, all pointers are valid and "this" is accessible to all methods but after being called from setTimeout the loop() method loses its "this" reference, and yet the Bark method (called from loop via the function pointer) retains it.

    The only difference is that the function poointer for Dump AND Loop is passed in when the dog dumps, but only the function pointer for Bark is passed in when the dog barks.

    Why can I not define these function pointers in the class declaration, and have them still be valid even when called from a different thread via the setTimeout?

    Code:
    <html>
    <head>
    <title>Object Test</title>
    <SCRIPT>
    function Dog()
    {
        this.instance   = 0;
        
    	this.BarkString = "Woof";
    	this.DumpString = "Dumping away like a dog.";
    	this.Bark = function(){alert("Bark has access to this.BarkString: (" + this.BarkString  + "), because it was passed in as a param");};
    	this.Dump = function(){alert("Dump has access to this.DumpString: (" + this.DumpString + "), because it was passed in as a param");};
    	
    	this.StartLoop = function(numLoops, ptrCall, ptrOptional)
    	{
    	    m_Method 	= ptrCall;
    	    // If they pass up the loop method, then use it, else use the default member var 
    	    if (ptrOptional)
    	        m_LoopMethod = ptrOptional;
    		
    		m_CurrLoop 	= 0;
    		m_NumLoops 	= numLoops;
    		this.Loop();
    	};
    	this.Loop = function()
    	{
    	    // In this method we cannot access the "this" propery...!!!
    	    if (m_CurrLoop == 0)
    	        alert("First time through, we are called in the UI thread so DO have access to this.BarkString: " + this.BarkString);
    	    else
    	        alert("So why now can I Access: m_memberString (" + m_MemberString + ") but not this.BarkString(" + this.BarkString + ") UNLESS we passed the function in (as when we are Dumping)??");
    		
    		m_Method();
    		if (m_CurrLoop++ < m_NumLoops)
    			setTimeout(m_LoopMethod, 1000);
    	};
    	var m_MemberString  = "Member String";
    	var m_NumLoops 		= 0;
    	var m_CurrLoop 		= 0;
    	var m_LoopMethod 	= this.Loop;
    	/* Note this does not work 
    	var m_LoopMethod 	= function(){this.Loop()};
    	*/
    	var m_Method		= this.Bark;
    }
    
    
    var dog = 0;
    function MakeDog()
    {
    	dog = new Dog();	
    }
    
    function Bark()
    {
    	dog.StartLoop(5, function(){dog.Bark()});	
    }
    function Dump()
    {
        // Do a dump but pass in the loop method, meaning that when it executes
    	dog.StartLoop(4, function(){dog.Dump()}, function(){dog.Loop()});
    }
    </SCRIPT>
    </head>
    
    <body onload="MakeDog()">
        <span style="font-family: Arial"><strong><span style="font-size: 14pt">Why is it?<br />
        </span>
            <br />
            Why is it </strong>that when the dog Barks, the .Loop() method loses its "this" reference (gets set to that of the page!!) but when the dog does a poo, the fact that the calling code passes a reference to the .Loop() method, the loop method
            retains its "this" reference?</span><br />
        <br />
    <button onclick="Bark()">Start Barking (loses "this")</button>
    <button onclick="Dump()">Start Dumping (retains "this")</button>&nbsp;<br />
        <br />
        <span style="font-family: Arial">Why do I have to pass in a reference to the function?
            Why cannot the class define this internally? if it can, how do I?
        </span>
    </body>
    </html>

  • #2
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    "this" is a special keyword that always refers to the executing context, it is a dynamic reference and is evaluated each time it is encountered.

    All other variables are static references to their defining context, and once the referrent is determined, it does not change.

    This has interesting implications for object-oriented programming in JavaScript. You can read a lot more on the "this" keyword at http://www.quirksmode.org/ in his JavaScript section, or do some research on google.

    To fix your problem though, your object should have a private variable that stores the defining context and that should be used in place of this when attempting to refer to public members of your object from within the object:

    Code:
    function Dog()
    {
      var self = this;
      this.sound = "woof";
    
      this.bark = function()
      {
         alert(self.sound);
      }
    }
    This technique allows you to predictably access member variables from within the object in any execution context.

  • #3
    VR2
    VR2 is offline
    New Coder
    Join Date
    Jul 2006
    Posts
    39
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Wow, nice idea, thanks, that might *just* work

    I'll give it a try...

  • #4
    VR2
    VR2 is offline
    New Coder
    Join Date
    Jul 2006
    Posts
    39
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That is fantastic - it *WORKS*!!!!!

    This is going straight into my "Best Practices" when writing javascript classes. Why have I never heard of this before?

    As you say, the key is that this allows you to
    predictably access member variables from within the object in any execution context.
    and thus is very useful to know indeed. Essential tip!

    Many, many thanks again


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •