Question

I have a Factory class that I use in JavaScript to dynamically load a class file over AJAX and then return an object. I have run into a VERY peculiar bug in the system though that throws errors in EVERY browser, but under a condition that is beyond my ability to explain.

Here is a simplified version of my Factory class (I removed a lot of type checking and error handling to cut it down to bare minimum).

function Factory(){
    // This holds which files have already been loaded
    var loaded=new Object();

    // Returns a new object
    this.getObject=function(className,methodName,methodData){

        if(loadFile('class.'+className+'.js')){

            // Making sure that the object name is defined
            if(window[className]!=null){

                // Has to be an object
                if(typeof(window[className])=='function'){

                    // Creating a temporary object
                    return new window[className];
                }
            }
        }
    }
    // Loads a file over AJAX
    var loadFile=function(address){

        // Loads as long as the file has not already been loaded
        if(loaded[address]==null){

            // Required for AJAX connections (without ASYNC)
            var XMLHttp=new XMLHttpRequest();
            XMLHttp.open('GET',address,false);
            XMLHttp.send(null);

            // Result based on response status
            if(XMLHttp.status===200 || XMLHttp.status===304){

                // Getting the contents of the script
                var data=XMLHttp.responseText;

                // Loading the script contents to the browser
                (window.execScript || function(data){
                    window['eval'].call(window,data);
                })(data);

                // makes sure that file is loaded only once
                loaded[address]=true;
            }
        }
    }

This is what the user does:

 var Factory=new Factory();
 var alpha=Factory.getObject('example');
 alpha.set(32);
 alpha.get();
 var beta=Factory.getObject('example');
 beta.set(64);
 alpha.get();
 beta.get();

This fails, it says 'object is not a function' when the function is run for the second time (at the return new window[className]; line). I understand if I am missing something here, BUT here's the kicker:

If I prefix className in my window[] calls, then it works. For example, if I change my 'example' class filename to 'test_example' and then have these lines:

... if(window['test_'+className]!=null){ ...
... if(typeof(window['test_'+className])=='function'){ ...
... return new window['test_'+className]; ...

Then it works and both alpha and beta objects work as expected. When I refer to them purely through a variable, they fail. I tried things like className.toString() without success and even this fails:

className+''

This is really weird, I don't know where to look and what to try out anymore, does anyone know why this happens?

EDIT: Here is an example of the 'example.js' script that is being loaded:

function example(){

    var myVar=16;

    this.set=function(value){
        myVar=value;
    }

    this.get=function(){
        alert(myVar);
    }

}

(and if I rename this to test_example() and load the functions as shown above with constructed strings, then it again works)

Was it helpful?

Solution

I figured out where the error was, which my above, cut-down version does not show. Apparently I named my new variable the same that the name of the class itself was, thus after first initialization it got overwritten.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top