Javascript 调用;新";在Coffeescript中以编程方式

Javascript 调用;新";在Coffeescript中以编程方式,javascript,coffeescript,Javascript,Coffeescript,可能重复: 我希望能够以编程方式调用new。例如,如果我有这两个类: class Bird constructor: (@name) -> class Snake constructor: (@name) -> 我可以调用s=newsnake(“Sam”)。现在,我想做的是 bird_class = "Bird" b = new bird_class() 并且能够从字符串构造一个bird对象。这在CoffeeScript或Javascript中可能吗?我不是一个C

可能重复:

我希望能够以编程方式调用
new
。例如,如果我有这两个类:

class Bird
   constructor: (@name) ->

class Snake
   constructor: (@name) ->
我可以调用
s=newsnake(“Sam”)
。现在,我想做的是

bird_class = "Bird"
b = new bird_class()

并且能够从字符串构造一个bird对象。这在CoffeeScript或Javascript中可能吗?

我不是一个Coffeescripter,但在Javascript中,您可以做到:

 function MyClass() { ... constructor ... };
 function MyOtherClass() { ... other constructor ... };

 var theConstructor = something ? MyClass : MyOtherClass;

 var obj = theConstructor();
您只需获取对构造函数的引用,并将其视为一个值,随意处理即可


如果你想点名,那就有点棘手了。除了使用
eval()
(如果您愿意,也可以这样做,如果您可以确定这样做对您的项目没有风险的话),在JavaScript中不可能获得这样的符号引用。但是,如果它是对对象属性的引用,则它确实有效。

如果将类保留在对象中,则始终可以:

var animals = {
  Snake: Snake,
  Bird: Bird
};

new animals["Snake"]();
根据您的评论,这样的模式可以让您注册类 在飞行中。这是生的,但可能会给你一个想法:

var zoo = {
  animals: {},

  add: function (animal) {
    this.animals[animal.name] = animal;
  },

  make: function(name) {
    if (this.animals[name]) {
      return new this.animals[name]();
    }
  }
};

function Snake() {};
zoo.add(Snake);
var snake = zoo.make('Snake');

如果您在回答上述链接问题时确实使用了这种方法,请意识到您将需要导出类,例如,
window.Bird=Bird
@icktoofay谢谢您的提醒。有没有一种方法可以在不导出类的情况下执行此操作?使用上述方法,将发生以下情况:包含一个脚本。脚本使用
窗口添加引用。Bird=Bird
。然后我用coffeescript调用
新窗口['Bird']
?这是可行的,但如果有其他方法的话会很有趣。是的,但是如果没有
eval
(这可能是危险的,并且会阻碍可能的优化),您就必须将它们都放在一个对象中。@icktoofay有没有办法扩展var
bird\u类
来获取值,这样我就可以调用eval了?问题是我只有变量
bird\u class
可以工作with@Scoop:是的,但我会这样做:
bird\u class=eval bird\u class\u name;my_bird=new bird_class(arg1,arg2)
或在一条语句中,
new(eval bird_class_name)(arg1,arg2)
。当然,可以省略参数,但更令人惊讶的是,如果没有参数,可以省略参数括号。(你不能省略
(eval bird\u class\u name)
周围的括号)我需要能够做到这一点,而不必事先知道类的列表。你在某处定义了它们,对吗?定义过程的一部分可能是将它们注册到
动物
,或任何有趣的地方。我明白你的意思。将
zoo
做得更好,然后将每个类追加到
窗口中
?在大多数情况下,您都希望避免向窗口中添加大量变量。通常情况下,最好将内容封装在对象或模块中。首先,这样就不会与窗口名称空间中的其他代码发生冲突。另外,使用这样的工厂型解决方案,您将能够更好地对所有类进行封装。e、 g.您想查看定义的动物类的数量吗?:
zoo.animals.length
哈哈,对不起,我猜应该是
Object.keys(zoo.animals.length
。。。被我自己的打字错误愚弄了(我把动物当作一个数组)除了
eval()
,还可以使用
窗口(或者
这个
窗口的引用
):
b=新窗口[bird_class]()
,尽管它与
eval()
有同样的问题(虽然稍微安全一些).如何使用
eval
?有没有办法将var
bird\u类
扩展到var的值,这样我就可以调用eval了?@Scoop:
eval('a')
将获得名为
a
的变量的值,但是,如果用户输入,这有点危险,因为它还可以计算其他表达式。@Scoop:这也使得不可能安全地缩小代码变得非常困难,因为缩小器不会知道您传递给
eval
的所有可能的内容。