【问题标题】:Call "new" programmatically in Coffeescript [duplicate]在 Coffeescript 中以编程方式调用“new”[重复]
【发布时间】:2013-01-20 01:24:51
【问题描述】:

可能重复:
How do I make JavaScript Object using a variable String to define the class name?

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

class Bird
   constructor: (@name) ->

class Snake
   constructor: (@name) ->

我可以打电话给s = new Snake("Sam")。现在,我想做的是

bird_class = "Bird"
b = new bird_class()

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

【问题讨论】:

  • 如果您确实在上述链接问题的答案中使用了该方法,请意识到您需要导出您的类,例如 window.Bird = Bird
  • @icktoofay 感谢您的提醒。有没有办法在不导出类的情况下做到这一点?使用上述方法,会发生什么情况: 包含一个脚本。该脚本使用window.Bird = Bird 添加引用。然后用咖啡脚本我打电话给new window['Bird']?它有效,但如果有另一种方法会很有趣。
  • 是的,但是如果没有eval(这可能很危险并且会阻碍可能的优化),您必须将它们全部放在一个对象like numbers1311407's answer shows中。
  • @icktoofay 有没有办法扩展 var bird_class 以获取值,以便我可以调用 eval 呢?问题是我只有变量 bird_class 可以使用
  • @Scoop:是的,但我会这样做:bird_class = eval bird_class_name; my_bird = new bird_class(arg1, arg2) 或在一个声明中,new (eval bird_class_name)(arg1, arg2)。当然,可以省略参数,但更令人惊讶的是,如果没有参数,您可以省略参数括号。 (您不能省略 (eval bird_class_name) 周围的括号。)

标签: javascript coffeescript


【解决方案1】:

如果你将你的类保存在一个对象中,你总是可以:

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

【讨论】:

  • 我需要能够在事先不知道课程列表的情况下做到这一点
  • 你在某个地方定义了它们,对吧?定义过程的一部分可能是将它们注册到animals 或其他任何东西。
  • 啊有趣。我明白你在说什么。使zoo 更好然后将每个类附加到window 上?
  • 在大多数情况下,您会希望避免在 window.xml 中添加大量变量。通常最好将事情保密,在对象或模块中。一方面,您将没有机会以这种方式与窗口名称空间中的其他代码发生冲突。加上像这样的工厂类型解决方案,您将能够更好地保护所有类。例如你想看看定义的动物类的数量吗?:zoo.animals.length
  • 哈哈抱歉,我猜那是Object.keys(zoo.animals).length...被我自己的错字愚弄了(我有动物作为数组)
【解决方案2】:

我不是 Coffeescripter,但在 JavaScript 中你可以这样做:

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

 var theConstructor = something ? MyClass : MyOtherClass;

 var obj = theConstructor();

您可以获取对构造函数的引用并将其视为一个值,随心所欲地调整它。

如果你想通过 name 来做,那有点棘手。如果没有使用eval()(如果你愿意,你可以这样做,并且如果你可以确定它对你的项目没有风险),就不可能在 JavaScript 中获得对符号的引用。但是,如果它是对对象属性的引用,它确实有效。

【讨论】:

  • 除了eval(),还可以使用window(或this引用window):b = new window[bird_class](),尽管它与eval()有同样的问题(虽然稍微安全一些)。
  • eval 怎么办?有没有办法将 var bird_class 扩展为 var 的值,以便我可以在其上调用 eval?
  • @Scoop:eval('a') 将为您提供名为a 的变量的值,但考虑到用户输入,这有点危险,因为它也可以评估其他表达式。
  • @Scoop:这也使得安全地缩小代码变得非常困难,因为缩小器不会知道你传递给eval的所有可能的东西。
猜你喜欢
  • 2012-12-31
  • 2012-08-12
  • 1970-01-01
  • 2012-09-01
  • 2017-12-25
  • 2011-01-12
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
相关资源
最近更新 更多