3

CoffeeScriptで記述されたクラスの名前空間を作成するにはどうすればよいですか?

たとえば、ツリークラスAaBbCcがあります。私はそれらをグローバルに評価可能な名前空間-MyClassesに挿入しそれらを越えて通信し、jasmine-nodeでそれらを使用できるようにします。

class MyClasses.Aa
 @someProp: true

class MyClasses.Bb
 @someProp2: false

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

それらを1つのファイルに挿入してコンパイルすることはできますが、1つのクラス=1つのファイルが必要です。

どうすればいいですか?ありがとうございました!

編集:私はこの方法を試しましたが、それは良くないと思いますが、ブラウザとジャスミンノードで動作します

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

root.MyClasses.Aa = 

  class Aa
4

3 に答える 3

2

RequireJSを使用します。

「my-classes.coffee」という1つのファイルで、名前空間を定義します。

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このようにすることの問題の1つは、ステートメントの「my-classes」だけに依存できないことです。あなたがそれをした場合、MyClasses.Aa未定義になります。ただし、「aa」はMyClassesに追加する以外は何もエクスポートしないため、「aa」だけに依存することはできません。上記のコードスニペットでは、MyClasses.Bb明示的に依存していないため、は未定義です。これが、多くの人が1つの巨大なファイルを使用するか、名前空間を再エクスポートするという定型文を複製する理由です。

誰かがこれを修正する方法を知っているなら、私に知らせてください。

個人的には、RequireJSの使用は複雑であり、設定にはさまざまな方法があります。私がジャスミンでそれを使用した1つの方法は、ケーキタスクを使用して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

これは最善の方法ではないかもしれませんが、ブラウザー、ノードサーバー、およびジャスミンノードテストでモジュールを実行するために使用できました。また、スペックファイルの定型文を避けるためにカスタムランナーを使用する人もいます。

RequireJSを使用したくない場合は、この質問が役立つ場合があります。これは、 CoffeeScriptFAQnamespaceで定義されている関数を使用して機能します。

于 2012-11-27T19:46:46.363 に答える
1

Coffescriptwikiに提案された解決策があります:

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!'
于 2013-08-22T10:54:42.160 に答える
0

-b安全ラッパーを削除するフラグを使用してCoffeeScriptファイルをコンパイルできます。または、すでに持っているようなものを使用して、クラスをグローバルスコープに公開します

コーヒー

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

class MyClasses.Aa
  @someProp: true

b。コーヒー

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

c。コーヒー

# 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

他のクラスについても繰り返します。window最初の行では、よりもはるかに明示的であることがわかります。また、2番目の行では、名前空間の長いシーケンスなしでthisクラスを追加することができます。MyClasses

ブラウザでは、クラスはグローバルオブジェクト内にありますMyClasses

node.jsでは、次のように使用します(これは少し冗長なIMHOです)。

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でチェックしていません。

于 2012-11-27T01:50:13.820 に答える