nantekkotai's blog

おもに技術とお仕事に関連することを書いています。

CoffeeScriptで作成したClassにグローバルからアクセスできない -> 解決

CoffeeScriptでClassを作った場合、そのクラスをグローバルから参照出来ないんじゃん思った。

例えば、

class Hoge
  constructor: (@param) ->
    @name = @param.name
  
  setName: (name) ->
    @name = name
  
  getName: ->
    @name

このCoffeeScriptをコンパイルすると以下のようなJSファイルが出力される。

(function() {
  var Hoge;
  Hoge = (function() {
    function Hoge(param) {
      this.param = param;
      this.name = this.param.name;
    }   
    Hoge.prototype.setName = function(name) {
      return this.name = name;
    };  
    Hoge.prototype.getName = function() {
      return this.name;
    };  
    return Hoge;
  })();
}).call(this);

このとおり即時関数によって、グローバルスコープから切り離されている。
このままだと、

var hoge = new Hoge(); // -> undefined

ということになり、外部から使い物にならならない。
格好悪いけど、最初のCoffeeScriptのソースに以下の文を追加する必要がある。

@Hoge = Hoge

これによりグローバルからアクセス出来る。
出力されるJSファイルは以下の通り。

(function() {
  var Hoge;
  Hoge = (function() {
    function Hoge(param) {
      this.param = param;
      this.name = this.param.name;
    }   
    Hoge.prototype.setName = function(name) {
      return this.name = name;
    };  
    Hoge.prototype.getName = function() {
      return this.name;
    };  
    return Hoge;
  })();
  this.Hoge = Hoge;
}).call(this);

でも、こんなことするのはカッコ悪いよなあ、などと思って少し調べたらやっぱりやり方を間違っていました。。。

一体何を間違えていたのか。

オプションです。今まではこうやっていました。

$ coffee -c hoge.coffee

これでhoge.jsを出力していました。

ただし、-cオプションだけだと即時関数でスコープを区切られてしまいます。
なので以下のように-bオプションも付け加えます。

$ coffee -cb hoge.coffee

以下のように出力される。

Hoge = (function() {
  function Hoge(param) {
    this.param = param;
    this.name = this.param.name;
  }
  Hoge.prototype.setName = function(name) {
    return this.name = name;
  };  
  Hoge.prototype.getName = function() {
    return this.name;
  };  
  return Hoge;
})();

オプション(-b)を指定することでグローバルに登録されるという訳です。
始めからちゃんとドキュメントを読んでいればこんな問題にぶつからずに済んでいたのですね。
ドキュメントにはちゃんと目を通しましょう!