2011-10-30 26 views
1

我最近开始在CoffeeScript中开发一个不平凡的项目,我正在努力处理注册输出等问题。我正在以非常'pythonesque'的方式编写它,单个文件有效地成为相关类和功能的“模块”。我正在寻找的是在本地定义类和函数的最好方法,并且尽可能少地重复地在exports/window中定义。NodeJS:保持库文件DRY

目前,我使用的每一个文件下面,保存在文件中写exports.X = X一切:

class module 
    # All classes/functions to be included in exports should be defined with `@` 
    # E.g. 
    class @DatClass 

exports[name] = item for own name, item of module 

我也看了使用功能的可能性(比如, publish),它将在传递类exports/window取决于它的名字:

publish = (f) -> 
    throw new Error 'publish only works with named functions' unless f.name? 
    ((exports ? window).namespace ?= {})[f.name] = f 

publish class A 
# A is now available in the local scope and in `exports.namespace` 
# or `window.namespace` 

然而,这不符合功能工作的,据我所知,他们不能在CoffeeScript中“命名为”(E 。G。 f.name始终为''),因此publish无法确定正确的名称。

有什么方法可以像publish一样工作,但可以使用函数吗?或者处理这个问题的其他方法?

回答

2

这是一个丑陋的黑客攻击,但你可以使用以下命令:

class module.exports 
    class @foo 
    @bar = 3 

然后:

require(...).foo.bar // 3 
+0

哈克,当然,但坦率地讲整洁。 Works/w函数,如果你声明像@fn =(args ...) - >'fn()'的结果。我对于一个人会非常想用这个.. –

+1

这非常整齐。是什么让它变得拙劣? – connec

+0

在我看来,这只是一种轻率的冒险行为,因为它不是任何官方文档中提到的技术。尽管如此,这也可能与Node&CoffeeScript的btw有关。 –

0

(function (exports) { 
    // my code 

    exports.someLib = ... 
})(typeof exports === "undefined" ? window : exports); 

是一个巧妙的方法应该做你想做的。

如果编写包装器样板文件是一个痛苦,然后使用构建脚本自动化它。

+0

我相信CoffeeScript中已经不正是当它编译脚本。我的问题是,定义类正确地导致重复:'exports.SomeClass = class SomeClass',没有第二个'SomeClass'结果函数将不会有'name'属性,这禁止了有用的反射。 – connec

+0

@connec那么是什么?认真。只需执行'class SomeClass',然后执行'exports.SomeClass = SomeClass'。我不称之为重复,我称这具有明确的出口。 – Raynos

+0

够公平的,但我希望有一个更简洁的解决方案。如果你只有几个类,但是对于有几十个类的模块(例外,令牌,节点等),你的方法没有问题,这将是非常单调和容易出错的。 – connec

0

我正在寻找的是用尽可能少重复地定义类和函数在本地和exports/window的最佳途径。

这是不可能做到像

exports.x = var x = ...; 

东西没有用JavaScript编写x两次(而不是诉诸黑magicks,即eval),同样也适用于CoffeeScript的。 Bummer,我知道,但事情就是这样。

我的建议是不要太挂在上面;这种重复是常见的。但是请问自己:“我是否真的需要导出这个函数或变量使它在本地可用?”干净的解耦代码通常不会那样工作。

0

“no named functions”规则有个例外:classes。这工作:http://jsfiddle.net/PxBgn/

exported = (clas) -> 
    console.log clas.name 
    window[clas.name] = clas 
... 
exported class Snake extends Animal 
    move: -> 
    alert "Slithering..." 
    super 5