动态对象创建

问题描述:

我有一个功能,需要一个字符串对象的名字,我需要的功能,以创建具有相同的名称作为字符串动态对象创建

例如值的对象的新实例,

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

虽然我知道这将是可能的通过评估,这将是很好的尝试和避免使用它。我如果任何人有一个替代的想法也很感兴趣的问题(下)


我有一个数据库和一套(使用传统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这导致我上面的问题...

为什么不简单地通过构造函数函数转换为require方法?这样你避开了从名称到功能转换的整个问题。那么你的榜样看起来像:

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

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

你为什么deadset使用eval避免?它是一种语言中的工具,每种工具都有其用途(就像每一种工具都可能被滥用一样)。如果您担心允许任意执行,则简单的正则表达式测试应该可以确保您的使用安全。

如果你死心塌地就避免eval,如果您的所有构造函数在默认的全球范围内创建(即window对象),这会工作:

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

首先,谢谢你的回应。像往常一样,在回顾一个答案后,我觉得有点愚蠢,因为错过了一些(回想起来相当明显)的东西。在这种情况下,字符串更容易,但是通过构造函数(我不知道可以这样做)看起来更简洁,更重要的是清晰。我并不是反对使用eval,并且正如你所说的那样,它有它的位置,但是经验告诉我,如果我认为我需要使用它的时候有99%的时间我不懂这门语言。 (这是其中的一次)。 – Yacoby 2010-07-09 22:51:15

+0

@Yacoby说得好! :)尤其是最后的句子。我希望大家都会这样想。 – galambalazs 2010-07-09 22:53:32

+0

这是一个很好的答案。学习了关于JavaScript的新内容!谢谢:) – rossipedia 2010-07-09 23:32:27

你是在完整的门虽然安娜贝尔的解决方案让我们你做什么你只是想在你想要的方式。 (通过字符串),让我为您提供一个替代方案。 (传递函数的引用)

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

而且瞧,它的工作原理 :)我告诉你。你在解决方案的门槛上。

发生了什么事是你已经尝试这样做

new 'Foo'() 

这并不使多大意义,不是吗?但是现在你通过引用来传递函数,所以行return new name();将被转换为return new Foo();,就像你期望的那样。

现在打开门以提取应用程序的异步性。玩的开心!

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

+0

'require()'的第二个和第三个参数仍然必须是字符串,它们标识的对象是还不存在的对象的属性。 – Annabelle 2010-07-09 22:57:39

+0

是的你是对的。 – galambalazs 2010-07-09 23:32:50