实例化从字符串名称中获取参数数组的 JS 对象

Instantiate JS Object that take array of arguments from String name

我有一个接受多个参数的 JS class:

var MyClassName = function(arg1, arg2, arg3){ // Do stuff };

我有一个代表 class 名称的字符串,以及一个参数数组。

var class = "MyClassName"
var args = ["1", "2", "3"]

使用 class 名称的字符串和参数数组,如何实例化 class?原型 Bind/apply 似乎有一定的相关性,但我不太清楚这一切是如何协同工作的。我也尝试过使用 window["MyClassName"],但这会引发未定义的错误。有什么建议吗?

您可以使用 eval:

var a = eval("new " + className + " ( " + arguments.toString() + ")");

示例:

JSFIDDLE:https://jsfiddle.net/s40ave7r/

function A(a1,a2,a3) {
    this.a1 = a1;
    this.a2 = a2;
    this.a3 = a3;
}

var className = "A";
var arguments = [1,2,3];

var a = eval("new " + className + " ( " + arguments.toString() + ")");

console.log(a); // A {a1:1, a2:2, a3:3}

:

通常使用 eval 是个坏主意。如果可以尽量避免。这些是与eval相关的一些问题:

  1. 不正确地使用 eval 会打开您的代码进行注入攻击
  2. 调试可能更具挑战性(没有行号等)
  3. eval 的代码执行得更慢(没有机会 compile/cache eval'代码)

解决方案 2

其他解决方案是将 class 定义附加到对象。例如,当你在全局范围内定义一个 class 时,它默认附加到浏览器中的 window 对象,或者附加到节点中的 global 对象。所以你可以这样做:

浏览器

function MyClass() {}
new window["MyClass"](arg1, arg2..);

节点

function MyClass() {}
new window["MyClass"](arg1, arg2..);

您可以将 'class' 定义为

window.MyClassName = function( arg1, arg2, ... ) {
    this.arg1 = arg1;
    //...
};

然后你可以用

调用它
var instance = new window['MyClassName']( arg1, arg2, ... ) 

或与

var instance = new window.MyClassName( arg1, arg2, ... );

或者最好不要使用 window,使用自己的对象。

var classes = {
    MyClassName: function( arg1, arg2, ... ) {
        this.arg1 = arg1;
        //...
    }
};

var instance = new classes.MyClassName( arg1 );

编辑:你说 window["MyClassName"] 不起作用,但是如果你在全局范围内定义一个 'class',那么你可以这样调用它。能否请您添加您所指的错误?

function testClass( arg1 ) {
    this.foo = arg1;
}

var instance = new window['testClass']( 'bar' );
console.log( instance.foo ); // The output will be bar

此代码有效,但您可能忘记了 'new'。如果您在没有 'new' 的情况下尝试此操作,则会在 Chrome:

处抛出此错误
Uncaught TypeError: Cannot read property 'foo' of undefined

谢谢大家的精彩建议。除了 this SO answer:

之外,我在这里合并了部分答案

var className = new window['MyClassName'] var instantiatedClass = className.bind.apply(className, [null, arg1, arg2, ...]);