【问题标题】:Javascript new object instance from dynamic function name来自动态函数名称的 Javascript 新对象实例
【发布时间】:2012-03-02 14:11:25
【问题描述】:

在 PHP 中,字符串可用于动态选择类进行实例化。以下是 PHP 中的 2 个简单类:

<?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);

我还看到 an approach 调用 Function 函数:

方法 #2

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

On the 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 的东西,其中字符串可以映射到要实例化的函数?

【问题讨论】:

  • 如何使用方法#2 将参数传递给新函数?所以它会像这样执行:new Genie('foo') foo 也是一个变量?
  • 找到了!它是这样的:var oGenius = new Function('arg1', 'return new ' + sClassName + '(arg1)')($argumentVariable);

标签: php javascript oop function dynamic


【解决方案1】:

我认为你涵盖了所有内容。但是,您可以通过记住全局变量和函数是窗口对象的属性来简化第三种方法,因此您可以使用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 在内部使用哈希表来引用对象属性,无论如何)。

【讨论】:

  • 绝对看起来是一种合理的方法,唯一的缺点是类可能无法移植到 node.js 等其他环境。但是我在问题中没有提到这一点:)
  • 您实际上不必修改声明类型的方式。您仍然可以只编写函数 Genie(){},然后使用 var o = new window["Genie"](); 创建一个实例
  • 啊@SynXsiS,这是一个很棒的提示,也是我见过的最干净的东西,谢谢。
猜你喜欢
  • 2013-09-27
  • 2021-04-19
  • 1970-01-01
  • 2010-12-23
  • 2017-09-28
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多