动态对象创建

时间:2010-07-09 22:15:11

标签: javascript dynamic object

我有一个带字符串对象名称的函数,我需要该函数来创建一个与字符串值相同的对象的新实例

例如,

function Foo(){}
function create(name){
    return new name();
}
create('Foo'); //should be equivalent to new Foo();

虽然我知道这可以通过eval实现,但尝试避免使用它会很好。我也有兴趣,如果有人对问题有另一种想法(下面)


我有一个数据库和一组(使用经典的OO方法)类,每个表大约有一个用于定义该表上常见操作的表。 (对于那些使用PHP的人来说,非常类似于Zend_Db)。由于一切都是异步的,因此根据最后一个结果执行任务可能会导致非常缩进的代码

var table1 = new Table1Db();
table1.doFoo({
    success:function(){
        var table2 = new Table2Db();
        table2.doBar({
            notFound:function(){
                doStuff();
            }
        });
    }
});

显而易见的解决方案是创建辅助方法,以抽象代码的异步性质。

Db.using(db) //the database object
  .require('Table1', 'doFoo', 'success') //table name, function, excpected callback
  .require('Table2', 'doBar', 'notFound')
  .then(doStuff);

简化了事情。然而问题是我需要能够创建表类,其名称可以从传递给require的第一个扩充中推断出来,这导致我上面的问题......

2 个答案:

答案 0 :(得分:4)

为什么不简单地将构造函数传递给require方法?这样你就可以回避从名称转换为函数的整个问题。您的示例将如下所示:

Db.using(db) //the database object
  .require(Table1Db, 'doFoo', 'success') //table constructor, function name, expected callback
  .require(Table2Db, 'doBar', 'notFound')
  .then(doStuff);

但是,如果你真的想使用字符串......

为什么你对避免使用eval感到厌烦?它是语言中的工具,每个工具都有其目的(正如每个工具都可以被误用)。如果您担心允许任意执行,那么简单的正则表达式测试应该可以使您的使用安全。

如果您已经设置为避免eval并且如果所有构造函数都是在默认的全局范围(即窗口对象)中创建的,那么这将起作用:

function create(name) {
  return new window[name]();
}

如果你想获得幻想并支持命名空间对象(即create('MyCompany.MyLibrary.MyObject')),你可以这样做:

function create(name) {
  var current,
      parts,
      constructorName;

  parts = name.split('.');
  constructorName = parts[parts.length - 1];
  current = window;
  for (var i = 0; i < parts.length - 1; i++) {
    current = current[parts[i]];
  }

  return new current[constructorName]();
}

答案 1 :(得分:2)

你是完整的大门。虽然Annabelle的解决方案让你以你想要的方式做你想要的事情(传递字符串),让我为你提供另一种选择。 (传递函数引用)

function Foo(){}
function create(name){
    return new name();
}
create(Foo); // IS equivalent to new Foo();

并且瞧,它有效 :)我告诉过你。你就在解决方案的门口。

发生了什么事,你试图这样做

new 'Foo'()

这没有多大意义,是吗?但现在您通过引用传递函数,因此行return new name();将转换为return new Foo();,就像您期望的那样。

现在打开门以抽象应用程序的异步性。玩得开心!

附录:函数是第一类对象,这意味着它们可以通过引用存储,通过引用作为参数传递或作为值返回给另一个函数。