如何通过字符串类型名称新建 Class 并在其中应用具有空值的数组参数?

How to new a Class by it's string type name and apply a array parameter inside which has null value?

  1. 我在别处定义了2个Class,所有的构造函数都需要3个 参数(a, b, c),但是a, b(object), c(object)在一个Array

    var paramArr = [a, b, c];
    
  2. 我想根据字典对象通过参数调用这 2 个 Class,例如:

    var dict = {'a': 'A', 'b': 'B'};
    

    然后,

    callClass(x){
      var className = dict[x];//string
      new className();
    }
    
  3. 所以,首先我尝试做类似 eval 的事情,这样我就可以用它的字符串名称调用 Class。

    callClass(x){
      var className = dict[x];//string
      var classFn = new Function(this, 'new ' + className + '()');
      classFn();
    }
    
  4. 仍然可以正常工作。最后我应该通过 Fn.prototype.apply() 添加 args,然后我不得不说一切都搞砸了:

    callClass(x){
      var className = dict[x];//string
      paramArr.unshift(null);
      var functionBodyStr = 'return new (Function.prototype.bind.apply(' + className + ', '+ paramArr +'))';
      var classFn = new Function(this, functionBodyStr);
      classFn();
    }
    

控制台中的 classFn 将是:

    function(this){
      return new (Function.prototype.bind.apply(Classname, , a ,[object Object],[object Object]))
    }

这是我所期望的,但不是全部:

首先将数组中的'null'值转换为消失,从而导致'unexpected token ,'

其次,所有其他对象都转换为'[object Object]',这导致'unexpected identifier'

那么,我怎样才能应用具有空值的数组参数呢?或者这是错误的方法?

如果我理解正确,您正在尝试创建 class/constructor 名称动态确定的对象。为此,您可以尝试使用 eval.

使用评估

想法

  • 根据您的要求创建 class/constructor 名称。
  • 使用 eval 查找此函数并获取其作用域。
  • 如果找到,可以直接使用new fn(...)
  • 如果没有找到,它会抛出错误,所以你必须处理这种情况。

function MyClass1(a, b, c) {
  this.a = a;
  this.b = b;
  this.c = c
}

function MyClass2(a, b, c) {
  this.a = a;
  this.b = b;
  this.c = c
}

var classPrefix = 'MyClass';
var result = [];
for (var i = 0; i < 5; i++) {
  var functionName = classPrefix + (i % 3 + 1);
  var fn;
  try {
    fn = eval(functionName);
    result.push(new fn(i, i+1, i+2));
  } catch (ex) {
    console.log(functionName + ' was not found. Please check again.')
  }
}

result.forEach(function(obj) {
  console.log(obj.constructor.name, obj.a)
})

参考文献:


使用 HashMap

这种方法的想法是使用地图列出可能的 类 并使用它来动态获取参考。这是 better/preferred 而非 eval 的方法,但它会带来维护地图的开销。

function MyClass1(a, b, c) {
  this.a = a;
  this.b = b;
  this.c = c
}

function MyClass2(a, b, c) {
  this.a = a;
  this.b = b;
  this.c = c
}

var functionMapper = {
  'MyClass1': MyClass1,
  'MyClass2': MyClass2,
}

var classPrefix = 'MyClass';
var result = [];
for (var i = 0; i < 5; i++) {
  var functionName = classPrefix + (i % 3 + 1);
  var fn = functionMapper[functionName];
  fn && result.push(new fn(i, i+1, i+2));
}

result.forEach(function(obj) {
  console.log(obj.constructor.name, obj.a)
})