代码之家  ›  专栏  ›  技术社区  ›  Yacoby

动态对象创建

  •  3
  • Yacoby  · 技术社区  · 14 年前

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

    例如,

    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 回复  |  直到 14 年前
        1
  •  4
  •   Annabelle    14 年前

    为什么不简单地将构造函数传递到 require

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

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

    你为什么死心塌地地避免使用 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]();
    }
    
        2
  •  2
  •   gblazex    14 年前

    你在完美无缺的门口。而安娜贝利的解决方案让你以你想要的方式做你想要做的事情 (传递字符串) ,让我给你一个选择。

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

    以及 瞧,它起作用了

    发生的事情是你试图这么做

    new 'Foo'()
    

    return new name(); 将转化为 return new Foo();

    现在打开了大门来抽象应用程序的异步性。玩得高兴!

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