如何在不使用eval的情况下在Coffeescript中动态创建命名类?

时间:2011-09-25 02:14:30

标签: coffeescript

我希望能写下来:

generate 'Cat', 'meow'

并以这样的方式定义generate函数:

class Cat
  meow: ->
    @.__proto__.constructor.name + ' says meow.'

所以我可以写:

garfield = new Cat
garfield.meow() # "Cat says meow"

2 个答案:

答案 0 :(得分:4)

如果你不介意污染你的全局命名空间,我实际上在CoffeeScript site的'try coffeescript'跑步者中运行了这个片段:

root = exports ? window
alert = alert or console.log

gen = (clsname, val) ->
  root[clsname] = class
    meow: => "#{clsname} says #{val}"

gen 'Cat', 'meow'
g = new root.Cat
alert g.meow()

gen 'Dog', 'woff'
d = new root.Dog
alert d.meow()

不是你要求的100%,但这几乎是你想要的,不是吗?

编辑:实际上,第一个脚本仅在浏览器中工作,而不是基于(Node.js的)CLI,更正了脚本。

如果您知道自己只能在浏览器中使用,则可以放弃root.Cat并只说Cat,但如果您想要Node.js 浏览器,请你将不得不忍受root.*

编辑2:从生成函数返回类通常是一个更好的主意,而不是神奇地将它放在命名空间中。也可以使方法名称动态化。来自提问者@Loren的一些灵感(注意它不再需要引用全局对象):

alert = alert or console.log

gen = (clsname, val) ->
  C = class
  C.prototype[val] = -> "#{clsname} says #{val}"
  C

Cat = gen 'Cat', 'meow'
console.log Cat
g = new Cat
alert g.meow()

Dog = gen 'Dog', 'woff'
d = new Dog
alert d.woff()

答案 1 :(得分:2)

如果“命名类”是指“具有命名功能的类”,那么您所要求的内容是不可能的 - 在CoffeeScript或JavaScript中。如果没有eval,则无法创建等效的function FuncName() {...}。您只能对使用该语法定义的函数使用__proto__.constructor.name属性。

class语法是在CoffeeScript中创建命名函数的唯一方法,原因如FAQ中所述。