1

让我们定义一只狗:

function Dog() {}

现在让我们定义一个将 Dog 作为参数传递的自执行函数:

(function(dogClassName) {

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

经过一些谷歌搜索后,我发现我应该使用

new window["dogClassName"]();

或者

new this["dogClassName"]();

但由于它是一个作用域变量,它不存在于全局名称空间(无窗口)中,并且thisundefined; 我不知道如何在不使用某种评估的情况下实现这一目标。

4

1 回答 1

2

对,假设您尝试访问未设置 global的构造函数,那么您的问题的答案很简单:您不能这样做。各种引擎对闭包的范围进行不同的管理。如果返回的函数没有显式引用它,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';
    };
}());

看看这个问题,在我看来是相关的,甚至是重复的。

更新犹豫,但为了完整性
有一种方法可以使用变量的值作为作用域链中的引用,但它确实需要最邪恶邪恶功能:eval('new '+ className + '()')正如你在规范中看到的那样,eval 将保留this绑定,并且重新初始化作用域链。除非你正在使用'strict mode';
因为你从 ajax 响应中获取构造函数名称,并且eval很容易被利用,所以不要这样做!这是一种“理论上,你可以......”的事情。

于 2012-11-07T09:57:56.060 回答