0

Hi i am beginning using the singleton javascript design pattern, but i have some scope problems. Here i am just experimenting with a small ajax, retrieve and store singleton. From within a function in the singleton i call another function (this.ready, called when the ajax has retrieved and stored the data) but it seems "this" doesn't refer to the singleton, rather it refers to "Object #XMLHttpRequest" according to chrome debugger, firefox just says it's undefined.

            var mag = {
                magObj: [], // object to store the retrieved json data

                getData: function(){
                    request = getHTTPObject(), // defined externally
                    request.onreadystatechange = this.setData;
                    request.open("POST", "be.php", true);
                    request.send(null);
                },

                setData: function(){  
                    if (request.readyState == 4)
                    {
                        this.magObj = JSON.parse(request.responseText);
                        this.ready(); // this line yields the error, seems "this" does not refer to the singleton

                    }
                    else if (request.readyState == 1)
                    {

                    }
                },

                ready: function() {
                    console.log('ready');
                },

                construct: function(){
                    this.getData();
                },  
            }

Also if i try to declare the getHTTPObject() as a singleton variable in the top, instead of using global variable i get the error Cannot read property 'readyState' of undefined. Again it's "this" getHTTPObject that seems to be undefined even though i set it at the top:

        var mag = {
            magObj: [],
            request: getHTTPObject(),

            getData: function(){

                this.request.onreadystatechange = this.setData;
                this.request.open("POST", "be.php", true);
                this.request.send(null);
            },

            setData: function(){  
                if (this.request.readyState == 4) // debugger says this.request is undefined
                {
                    this.magObj = JSON.parse(this.request.responseText);

                }
                else if (this.request.readyState == 1)
                {

                }
            },

            construct: function(){
                this.getData();
            },  
        }
c69
  • 19,951
  • 7
  • 52
  • 82
lowkey
  • 334
  • 1
  • 7
  • 17
  • 1
    "this" changes in javascript according to the calling function. Check out this answer http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean-in-javascript – David Sep 23 '11 at 16:09

3 Answers3

1

#1
setData is a callback function for the XMLHttpRequest object. It's therefore run in the scope of the XMLHttpRequest object. Use mag instead of this.

#2
Same as #1: this refers to the XMLHttpRequest, rather than you mag variable.

Rob W
  • 341,306
  • 83
  • 791
  • 678
1

If it is a singleton you could try

           var mag = {
            magObj: [], // object to store the retrieved json data

            getData: function(){
                request = getHTTPObject(), // defined externally
                request.onreadystatechange = this.setData;
                request.open("POST", "be.php", true);
                request.send(null);
            },

            setData: function(){  
                if (request.readyState == 4)
                {
                    this.magObj = JSON.parse(request.responseText);
                    mag.ready(); // this line yields the error, seems "this" does not refer to the singleton

                }
                else if (request.readyState == 1)
                {

                }
            },

            ready: function() {
                console.log('ready');
            },

            construct: function(){
                this.getData();
            },  
        }
Declan Cook
  • 6,066
  • 2
  • 35
  • 52
1

To solve the scope problem, you need to use the concepts of closures in javascript. basically a scope where functions have access to properties and methods in the context that created that function.. ok for a more clear explanation.. try initializing your mag object as a function..

var mag = function(){
    var magObj = [];
    var getData = function(){
        //here you'll have access to the magObj collection
    };
}

The previous is a classic example of a javascript closure.. Of course you instantiate the mag object simply as a function invocation mag();

Hope this helps.

Anas Karkoukli
  • 1,342
  • 8
  • 13