Node.js NodeJS:保持库文件干燥

Node.js NodeJS:保持库文件干燥,node.js,coffeescript,dry,Node.js,Coffeescript,Dry,我最近开始在CoffeeScript中从事一个非常重要的项目,我正在努力解决如何最好地处理注册导出等问题。我以一种非常“pythonesque”的方式编写它,单个文件实际上是相关类和函数的“模块”。我正在寻找的是在本地和导出/窗口中定义类和函数的最佳方法,重复次数越少越好 目前,我在每个文件中使用以下命令来保存文件中所有内容的写入exports.X=X: class module # All classes/functions to be included in exports should

我最近开始在CoffeeScript中从事一个非常重要的项目,我正在努力解决如何最好地处理注册导出等问题。我以一种非常“pythonesque”的方式编写它,单个文件实际上是相关类和函数的“模块”。我正在寻找的是在本地和
导出
/
窗口
中定义类和函数的最佳方法,重复次数越少越好

目前,我在每个文件中使用以下命令来保存文件中所有内容的写入
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
)的可能性,该函数根据传递的类的名称,将传递的类放入
导出
/
窗口

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中“命名”(例如,
f.name
总是
'
),因此
publish
无法确定正确的名称

是否有任何方法可以像
publish
那样工作,但可以与函数一起工作?或者其他处理方法?

旧的

(function (exports) {
  // my code

  exports.someLib = ...
})(typeof exports === "undefined" ? window : exports);
这是一个巧妙的技巧,应该做你想做的

如果编写包装器样板是一件痛苦的事,那么使用构建脚本将其自动化

我正在寻找的是在本地和
导出
/
窗口
中定义类和函数的最佳方法,重复次数越少越好

做这样的事是不可能的

exports.x = var x = ...;
不使用JavaScript编写两次
x
(不使用黑色魔法,即
eval
),咖啡脚本也是如此。糟糕,我知道,但事实就是这样


我的建议是不要太在意它;这种重复很常见。但是一定要问自己:“我真的需要导出这个函数或变量并使其在本地可用吗?”完全解耦的代码通常不是这样工作的。

对于“无命名函数”规则有一个例外:类。这项工作:


这是一个丑陋的黑客,但您可以使用以下方法:

class module.exports
  class @foo
    @bar = 3
然后:

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

我相信CoffeeScript在编译脚本时已经做到了这一点。我的问题是正确定义类会导致重复:
exports.SomeClass=class-SomeClass
,如果没有第二个
SomeClass
,结果函数将不会有
name
属性,这会禁止有用的反射。@connec那又怎样?认真地只需执行
classsomeclass
,然后在最后执行
exports.SomeClass=SomeClass
。我不称之为重复,我称之为定义良好的导出。这很公平,但我希望存在一个更简洁的解决方案。如果您只有几个类,但对于一个包含几十个类(异常、标记、节点等)的模块,您的方法是很好的。这将非常繁琐且容易出错。@connec为什么要导出几十个类。问题不在于它太单调乏味,问题在于你的API太臃肿了。虽然有点粗糙,但无可否认很整洁。如果您声明像@fn=(args…)->“fn()的结果”,那么也可以使用/w函数。就我个人而言,我很想用这个……这是非常整洁的。是什么让它有黑客感?在我看来,它只是有点黑客感,因为它不是任何官方文档中提到的技术。不过,这也可能与Node&CoffeeScript的椅子有关。这里有一个棘手的部分,您将函数(实际上是一个构造函数)分配给
模块.exports
,并以类似静态方法的形式向该函数添加属性,而不是将对象分配给
模块.exports
。此外,如果您需要在此模块中的某个地方使用
bar
,则需要使用完整路径
exports.foo.bar
,这是一个难题。由于样板咖啡脚本附加到编译的javascript:
(function(){…})。调用(this)-这意味着脚本的作用域已经是
模块。导出
,因此您可以删除外部
类模块。导出
定义并直接转到
类@foo
require(...).foo.bar // 3