使用动态函数名编写Javascript新对象实例


Javascript new object instance from dynamic function name

在PHP中,可以使用字符串来动态选择要实例化的类。以下是PHP中的两个简单类:

<?php
class Magic implements Genius {
  public function perform() {
    echo 'madya look :P' . PHP_EOL;
  }
}
class Genie implements Genius {
  public function perform() {
    echo 'your wish has been granted!' . PHP_EOL;
  }
}

现在可以有一个变量,使得在运行时实例化的类基于其内容

$sGeniusClass = 'Magic';
$oGenius      = new $sGeniusClass();

现在在Javascript中,我喜欢使用函数作为构造函数来具有某种类型化程度,在这种情况下,我可能会有:

function Magic() {}
Magic.prototype = {
  perform : function()
  {
    console.log('madya look :P');
  }
}
function Genie() {}
Genie.prototype = {
  perform : function()
  {
    console.log('your wish has been granted!');
  }
}

我知道我可以用eval:实现类似于PHP的东西

方法#1

var sClassName = 'Genie';
eval('var oGenius = new ' + sClassName);

我还看到了一种调用函数函数的方法:

方法#2

var sClassName = 'Genie';
var oGenius = new Function('return new ' + sClassName)();

在MDN上,尽管听起来每次创建实例时都会重新评估性能:

使用Function构造函数创建的函数对象在创建函数。这比声明函数并在代码中调用它,因为函数声明与函数语句一起被解析为与代码的其余部分一起被解析。

现在我有了一个有点乏味的方法:

方法#3

var aClassMap = {
  Magic : Magic,
  Genie : Genie,
  create : function(sClassName) {
    if(this[sClassName] === undefined)
      return false;
    return new this[sClassName];
  }
}
var sClassName = 'Genie';
var oGenius = aClassMap.create(sClassName);

总体而言,它似乎是我最喜欢的,没有使用eval,也没有后续的重新评估,就像解决方案#2一样。不过,这仍然有一些工作要做,所以我的问题有两个:

  1. 除了我展示的3种方法之外,还有其他方法可以做到这一点吗
  2. 有没有类似于PHP的东西,字符串可以映射到要实例化的函数

我想你涵盖了所有内容。然而,您可以通过记住全局变量和函数是窗口对象的属性来简化您的第三种方法,因此您可以使用window创建全局类,如下所示:

var myClassName = "Genie";
window[myClassName] = function {};
window[myClassName].prototype = {
  perform : function()
  {
    console.log('I am a ' + myClassName + ', and your wish has been granted!');
  }
}

我认为性能将一如既往地好(因为Javascript在内部使用哈希表来引用对象属性,不管怎样)。