Peeter
Peeter

Reputation: 9382

Initiate a scoped function from a string in javascript

Lets define a dog:

function Dog() {}

Now lets define a self executing function that passes the Dog as a parameter:

(function(dogClassName) {

    var someServerSideLogicResolvesClassName = "dogClassName";
    //Iniate class name from the server side string
})(Dog);​

After some googleing I found that I should use

new window["dogClassName"]();

or

new this["dogClassName"]();

But since it's a scoped variable it doesn't exist in the global name space (no window) and this is undefined; I have no idea how to achieve this without using some sort of evaling.

Upvotes: 1

Views: 72

Answers (1)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76433

Right, assuming that you're trying to access a constructor that isn't set globally, then the answer to your question is, quite simply: you can't do this. The scopes of closures are managed differently by the various engines. V8 might even GC the constructor if the returned function doesn't reference it explicitly...
There is no magic way to get a full outer scope as an object

The only solution would be to create a namespace-object:

(function()
{
    var constructors = {Constructor1: function(){},
                        Constructor2: function(){}};
    return function()
    {
        var className =getClassNameViaAjax();
        if (constructors.hasOwnProperty(className))
        {
            return new constructors[className]();
        }
        if (window[className] instanceof Function)
        {//fallback
            return new window[className]()
        }
        throw className + ' Does not exist in closure, nor in global scope';
    };
}());

Have a look at this question, it seems to me to be related, or even a duplicate.

Hesitant update, but for completeness
There is one way you can use a variable's value as reference in the scope chain, but it does require the most Evil of Evil functions: eval('new '+ className + '()'), as you can see in the specification, eval will preserve the this bindings, and reinitialize the scope chains. Except when you're using 'strict mode';
Since you're getting the constructor name from an ajax response, and eval is an easy thing to exploit, don't do this! This is a sort of an "in theory, you could..." thing.

Upvotes: 2

Related Questions