【问题标题】:NodeJS: Keeping library files DRYNodeJS:保持库文件干燥
【发布时间】:2011-10-30 17:07:53
【问题描述】:

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

目前,我在每个文件中都使用以下内容,以节省文件中所有内容的写入 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 中“命名”(例如,f.name 始终为 ''),因此 publish 无法确定正确的名称。

是否有任何方法可以像 publish 一样工作但适用于函数?或者任何其他的处理方式?

【问题讨论】:

    标签: node.js coffeescript dry


    【解决方案1】:

    这是一个丑陋的黑客,但你可以使用以下内容:

    class module.exports
      class @foo
        @bar = 3
    

    然后:

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

    【讨论】:

    • Hacky,当然,但诚然整洁。如果您声明像 @fn = (args...) -> 'results of fn()',也可以使用 /w 函数。我会很想用这个..
    • 这很整洁。是什么让它变黑了?
    • 在我看来,这只是轻微的hacky,因为它不是任何官方文档中提到的技术。不过,这也可能与它落在 Node 和 CoffeeScript 的椅子上有关。
    • hacky 部分是在这里,您将一个函数(实际上是一个构造函数)分配给 module.exports 并以类似静态方法的形式向该函数添加属性,而不是分配一个对象给 @ 987654324@。此外,如果您需要在此模块中的某处使用bar,则需要使用完整路径exports.foo.bar,这很痛苦。
    • 这实际上可以缩短,因为样板 Coffeescript 附加到已编译的 javascript:(function() { ... }).call(this); - 这意味着脚本的范围已经是 module.exports 所以你可以删除外部的 class module.exports定义并直接转到class @foo
    【解决方案2】:

    旧的

    (function (exports) {
      // my code
    
      exports.someLib = ...
    })(typeof exports === "undefined" ? window : exports);
    

    这是一个巧妙的技巧,应该做你想做的事。

    如果编写该包装器样板文件很痛苦,请使用构建脚本将其自动化。

    【讨论】:

    • 我相信 CoffeeScript 在编译脚本时已经做到了这一点。我的问题是正确定义类会导致重复:exports.SomeClass = class SomeClass,如果没有第二个SomeClass,则生成的函数将没有name 属性,这会禁止有用的反射。
    • @connec 那又怎样?严重地。只需执行class SomeClass,然后在最后执行exports.SomeClass = SomeClass。我不称之为重复,我称之为具有明确定义的导出。
    • 很公平,但我希望存在更简洁的解决方案。如果您只有几个类,则您的方法很好,但对于具有数十个类(异常、令牌、节点等)的模块,这将非常乏味且容易出错。
    • @connec 你为什么要导出几十个类。问题不在于乏味,问题在于你的 API 臃肿。
    【解决方案3】:

    我正在寻找的是在本地和exports/window 中定义类和函数的最佳方法,尽可能少地重复。

    这样的事情是不可能的

    exports.x = var x = ...;
    

    无需在 JavaScript 中写两次 x(无需使用黑魔法,即 eval),CoffeeScript 也是如此。糟糕,我知道,但事实就是这样。

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

    【讨论】:

      【解决方案4】:

      “无命名函数”规则有一个例外:类。这有效:http://jsfiddle.net/PxBgn/

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 2011-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多