为CoffeeScript类创建命名空间

为CoffeeScript类创建命名空间,coffeescript,Coffeescript,如何为用CoffeeScript编写的类创建名称空间 例如,我有树类Aa、Bb和Cc。我希望它们插入到全局可组装的名称空间-MyClasses,允许跨它们通信并在jasmine节点中使用它们 class MyClasses.Aa @someProp: true class MyClasses.Bb @someProp2: false class MyClasses.Cc @doSomeStuff: -> MyClasses.Aa.someProp = false 我知道,我可以

如何为用CoffeeScript编写的类创建名称空间

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

class MyClasses.Aa
 @someProp: true

class MyClasses.Bb
 @someProp2: false

class MyClasses.Cc
 @doSomeStuff: -> MyClasses.Aa.someProp = false
我知道,我可以将它们注入一个文件并进行编译,但我想要一个类=一个文件

请问我怎么做? 谢谢大家!

编辑:我试过这种方法,但我认为它不好,但它在浏览器和jasmine节点中工作

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

root.MyClasses.Aa = 

  class Aa

您可以使用
-b
标志编译CoffeeScript文件,该标志将删除安全包装。或者使用类似于您已经拥有的东西将您的类公开到全局范围

a、 咖啡 b、 咖啡 c、 咖啡 重复其他课程。在第一行中,我发现
窗口
更加明确,第二行也允许您只将类附加到
MyClasses
,而不需要长序列的名称空间

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

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


pd:我还没有和node jasmine核对过。

使用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.Bb
    @someProp2: false
现在,当您需要时,它应该导出
MyClasses
,其中包括
MyClasses.Aa

require ['my-classes', 'aa'], (MyClasses, _) ->
  console.log MyClasses.Aa.someProp
这样做的一个问题是,您不能只依赖
require
语句中的“我的类”。如果这样做,
MyClasses.Aa
将是未定义的。但是你也不能仅仅依赖于“aa”,因为“aa”除了通过添加到MyClass之外,不会导出任何东西。在上面的代码片段中,
MyClasses.Bb
是未定义的,因为我没有明确依赖它。这就是为什么许多人要么使用一个巨大的文件,要么复制重新导出名称空间的样板文件

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 = {}
如果有人知道如何解决这个问题,请告诉我

一、 就个人而言,发现RequireJS使用起来很复杂,有很多不同的方法来设置它。我在jasmine中使用它的一种方法是使用一个蛋糕任务将我的咖啡脚本预编译成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
这可能不是最好的方法,但我能够使用它在浏览器、节点服务器和jasmine节点测试中运行模块。我还看到一些人在他们的规范文件中避免使用样板文件


如果您不想使用RequireJS,您可能会发现它很有用。它通过使用上定义的
名称空间
函数来工作。

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

发件人:

#代码:
#
名称空间=(目标、名称、块)->
[目标、名称、块]=[(如果导出类型不是“未定义”,则导出其他窗口)、参数…]如果arguments.length<3
顶部=目标
target=target[item]或={}用于name.split.'中的项
顶住目标
#用法:
#
名称空间“Hello.World”(导出)->
#“exports”是附加命名空间成员的位置
exports.hi=->console.log“hi World!”
名称空间“Say.Hello”,(导出,顶部)->
#'top'是对主命名空间的引用
exports.fn=->top.Hello.World.hi()
Say.Hello.fn()打印“嗨,世界!”

为什么不使用requirejs/amd?有没有办法不用重复标题或使用requirejs就可以做到这一点?好的,我会使用requirejs,但是我怎样才能在jasmine节点测试中使用requirejs?用jasmine的例子更新了。我编写了这个测试,但当我开始它时,它会给我结果:
在0秒内完成0个测试,0个断言,0失败
请参阅有关的链接。这里也有一些例子。如果你还是不明白,我会问一个新问题。这不再是关于CoffeeScript中的名称空间,而是关于如何运行jasmine节点来测试RequireJS模块。
define ['my-classes'], (MyClasses) ->

  class MyClasses.Aa
    @someProp: true
define ['my-classes'], (MyClasses) ->

  class MyClasses.Bb
    @someProp2: false
require ['my-classes', 'aa'], (MyClasses, _) ->
  console.log MyClasses.Aa.someProp
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
# 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!'