14

I found this snippet on the Coffeescript FAQ for creating simplistic namespaces ..

# 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!'

That is all well and good, but I am having a great deal of trouble doing this with the class keyword. Such that ..

namespace 'Project.Something', (exports) ->
   exports.something = -> class something
    // .. code here
   exports.somethingElse = class somethingElse extends something

can anyone shed some light on the syntax that would accomplish this?

Ciel
  • 17,312
  • 21
  • 104
  • 199

3 Answers3

24

Even better, the class syntax allows for the name to actually be in the form of a member, so you can actually just do:

namespace 'Secrets', (exports) ->
  class exports.Hello
    constructor: ->
      @message = "Secret Hello!"

a = new Secrets.Hello
console.log a.message

Full fiddle here: http://jsfiddle.net/7Efgd/1/

Chris Subagio
  • 6,099
  • 1
  • 15
  • 7
  • This is a valid solution as well. It's really a matter of preference. I find the example above a little easier for me to understand. – Sandro Jan 29 '15 at 19:06
19

The trick is to create the class first

class MyFirstClass
  myFunc: () ->
    console.log 'works'

class MySecondClass
  constructor: (@options = {}) ->
  myFunc: () ->
    console.log 'works too'
    console.log @options

Then somewhere near the end of the file export all the classes than need to be exposed.

namespace "Project.Something", (exports) ->
  exports.MyFirstClass = MyFirstClass
  exports.MySecondClass = MySecondClass

Later on you can use the classes as so:

var firstClass = new Project.Something.MyFirstClass()
firstClass.myFunc()

var secondClass = new Project.Something.MySecondClass 
  someVar: 'Hello World!'

secondClass.myFunc()
user229044
  • 232,980
  • 40
  • 330
  • 338
Sandro
  • 4,761
  • 1
  • 34
  • 41
  • 1
    There we go! It was so simple, but so frustrating at the same time. Thank you! – Ciel Jan 04 '12 at 17:32
  • There should be a method that does this for you :( – jackyalcine Oct 23 '12 at 20:00
  • Doesn't this defeat the purpose of Namespacing? Seen as MyFirstClass is now defined both in the Namespace and outside of it? @ChrisSubagio's answer seems like a more correct way to do it. – Abe Petrillo Jan 29 '15 at 18:38
  • No. Coffeescript wraps that file within an anonymous function so `MyFirstClass` is not leaked to the global namespace. It's only exposed to the global namesapce through the `namespace` function. – Sandro Jan 29 '15 at 19:00
1

How about using something like this?

module =
    Hello: class Hello extends Backbone.Model
        constructor: ->
            @message = 'Hello'

    Hello2: class Hello2 extends Backbone.View
        constructor: ->
            @message = 'Hello2'
Sundar
  • 173
  • 1
  • 6