【问题标题】:Create namespace for CoffeeScript classes为 CoffeeScript 类创建命名空间
【发布时间】:2013-08-22 18:54:42
【问题描述】:

如何为我用 CoffeeScript 编写的类创建命名空间?

例如,我有树类 AaBbCc。我希望它们插入到全局可评估的命名空间 - MyClasses,允许跨它们通信并在 jasmine-node 中使用它们。

class MyClasses.Aa
 @someProp: true

class MyClasses.Bb
 @someProp2: false

class MyClasses.Cc
 @doSomeStuff: -> MyClasses.Aa.someProp = false

我知道,我可以将它们注入一个文件并编译,但我想要一个 class= 一个文件。

请问我该怎么做? 谢谢!

编辑:我尝试过这种方式,但我认为它不好,但它适用于浏览器和 jasmine-node

root = exports ? this
root.MyClasses = root.MyClasses ? {}

root.MyClasses.Aa = 

  class Aa

【问题讨论】:

  • 为什么不用requirejs/amd?

标签: coffeescript


【解决方案1】:

使用 RequireJS。

在一个名为“my-classes.coffee”的文件中,定义命名空间。

define [], ->
  # You need this if you want it to work in multiple environments.
  # Otherwise just use `window` to work in the browser.
  root = exports ? this

  root.MyClasses = {}

您可以在另一个名为“aa.coffee”的文件中定义您的课程。

define ['my-classes'], (MyClasses) ->

  class MyClasses.Aa
    @someProp: true

另一个文件:

define ['my-classes'], (MyClasses) ->

  class MyClasses.Bb
    @someProp2: false

现在,当您需要时,它应该导出MyClasses,其中包括MyClasses.Aa

require ['my-classes', 'aa'], (MyClasses, _) ->
  console.log MyClasses.Aa.someProp

这样做的一个问题是你不能只依赖require 语句中的“my-classes”。如果你这样做了,MyClasses.Aa 将是未定义的。但是你也不能只依赖“aa”,因为“aa”除了添加到 MyClasses 之外不会导出任何东西。在上面的代码 sn-p 中,MyClasses.Bb 是未定义的,因为我没有明确依赖它。这就是为什么很多人要么使用一个巨大的文件,要么复制重新导出命名空间的样板。

如果有人知道如何解决这个问题,请告诉我。

我个人觉得 RequireJS 使用起来很复杂,而且有很多不同的设置方法。我将它与 jasmine 一起使用的一种方法是使用蛋糕任务将我的 CoffeeScript 预编译为 JavaScript,然后生成这样的规范文件。

requirejs = require('requirejs')
# Set the baseURL to your compiled JS dir.
requirejs.config { baseUrl: __dirname + '/../lib' }

requirejs ['my-classes', 'aa'], (MyClasses, _) ->

  describe "someProp", ->
    it "should be true", ->
      expect(MyClasses.Aa.someProp).toEqual true

这可能不是最好的方法,但我能够使用它在浏览器、Node 服务器和 jasmine-node 测试中运行模块。我还看到有些人使用custom runners 来避免其规范文件中的样板。

如果您不想使用 RequireJS,您可能会发现 this question 很有帮助。它通过使用在CoffeeScript FAQs 上定义的namespace 函数来工作。

【讨论】:

  • 好吧,我将使用 RequireJS,但是如何将 RequireJS 与 jasmine-node 测试一起使用?
  • 更新了与 Jasmine 一起使用的示例。
  • 我写了这个测试pastebin.com/cn9T751j 但是当我开始它时,它会给我结果:Finished in 0 seconds 0 tests, 0 assertions, 0 failures
  • 查看custom runners的链接。 this project 中也有示例。如果您仍然无法弄清楚,我会问一个新问题。这不再是关于 CoffeeScript 中的命名空间,而是关于如何运行 jasmine-node 来测试 RequireJS 模块。
【解决方案2】:

在 Coffescript wiki 中有一个建议的解决方案:

来自https://github.com/jashkenas/coffee-script/wiki/FAQ

# Code:
#
namespace = (target, name, block) ->
  [target, name, block] = [(if typeof exports isnt 'undefined' then exports else window), arguments...] if arguments.length < 3
  top    = target
  target = target[item] or= {} for item in name.split '.'
  block target, top

# Usage:
#
namespace 'Hello.World', (exports) ->
  # `exports` is where you attach namespace members
  exports.hi = -> console.log 'Hi World!'

namespace 'Say.Hello', (exports, top) ->
  # `top` is a reference to the main namespace
  exports.fn = -> top.Hello.World.hi()

Say.Hello.fn()  # prints 'Hi World!'

【讨论】:

    【解决方案3】:

    您可以使用删除安全包装器的-b 标志来编译您的CoffeeScript 文件。或者用你已经拥有的东西将你的类暴露在全局范围内

    一杯咖啡

    root = exports ? window
    MyClasses = root.MyClasses = root.MyClasses ? {}
    
    class MyClasses.Aa
      @someProp: true
    

    b.coffee

    # same header as a.coffee
    class MyClasses.Bb
      @someProp2: false
    

    c.coffee

    # same header as a.coffee
    class MyClasses.Cc
      @doSomeStuffWith: (someClass)-> 
        # pass a class to the method instead of just 
        # modifying another class within the same scope
        someClass.someProp = false
    

    重复其他课程。在第一行中,我发现windowthis 更明确,第二行还允许您将类附加到MyClasses,而无需长序列的命名空间。

    在浏览器中,您的类将位于全局对象 MyClasses

    在 node.js 中,您可以像这样使用它们(恕我直言,这有点冗长):

    var Aa = require("./a").MyClasses.Aa,
        Bb = require("./b").MyClasses.Bb,
        Cc = require("./c").MyClasses.Cc;
    
    console.log(Aa.someProp)  // true
    console.log(Bb.someProp2) // false
    
    Cc.doSomeStuffWith(Aa)
    
    console.log(Aa.someProp) // false
    

    pd:我还没有用 node-jasmine 检查过。

    【讨论】:

    • 有什么方法可以做到这一点,而无需重复标题或使用 RequireJS?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    相关资源
    最近更新 更多