从javascript中的字符串启动作用域函数

从javascript中的字符串启动作用域函数,javascript,Javascript,让我们定义一只狗: function Dog() {} 现在,让我们定义一个自动执行函数,将Dog作为参数传递: (function(dogClassName) { var someServerSideLogicResolvesClassName = "dogClassName"; //Iniate class name from the server side string })(Dog);​ 在谷歌搜索之后,我发现我应该使用 new window["dogClassNa

让我们定义一只狗:

function Dog() {}
现在,让我们定义一个自动执行函数,将Dog作为参数传递:

(function(dogClassName) {

    var someServerSideLogicResolvesClassName = "dogClassName";
    //Iniate class name from the server side string
})(Dog);​
在谷歌搜索之后,我发现我应该使用

new window["dogClassName"]();


但由于它是一个作用域变量,因此它不存在于全局名称空间(无窗口)中,
未定义的
;我不知道如何在不使用某种评估的情况下实现这一点

是的,假设您试图访问的构造函数不是全局设置的,那么您的问题的答案很简单:您不能这样做。闭包的范围由不同的引擎进行不同的管理。如果返回的函数没有显式引用它,V8甚至可能GC构造函数
没有神奇的方法可以获得完整的外部作用域作为对象

唯一的解决方案是创建命名空间对象:

(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';
    };
}());
看一看,在我看来,这似乎是相关的,甚至是重复的

犹豫更新,但为了完整性

有一种方法可以使用变量的值作为作用域链中的引用,但它确实需要最EvilEvil函数:
eval('new'+className+'))
,eval将尽可能保留
this
绑定,并重新初始化作用域链。除非您使用的是
“严格模式”
由于您是从ajax响应中获取构造函数名称的,而且
eval
很容易利用,所以不要这样做!这是一种“理论上,你可以…”的东西。

只是澄清一下,“构造函数”函数不是在全局范围内设置的,对吗?这更像是一种
(function(){var someLocalConstructor=function(){};(function(){var className='someLocalConstructor';}())};())
情况?是的,没有一个变量在全局名称空间中(我使用requirejs,只是对代码进行了大量简化以显示用例),您能将其添加到某种容器对象吗?然后使用
newcontainerObj[“dogClassName”]()
。否则你需要使用eval。对变量的引用保存在哪里?@Peeter,对变量的引用保存在容器对象中,你知道该对象的名称,只需将类名用作属性,然后你就可以使用变量的值。我最后走了这条路,但我仍然觉得奇怪,我传入回调的所有变量都没有容器/引用点。谢谢。@Peeter:有时会很烦人,但范围链被视为内部烹饪,无法访问,还是这个非官方的
(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';
    };
}());