web-dev-qa-db-ja.com

CoffeeScriptでグローバル変数を定義するにはどうすればいいですか?

Coffeescript.orgでは、

bawbag = (x, y) ->
    z = (x * y)

bawbag(5, 10) 

にコンパイルされます:

var bawbag;
bawbag = function(x, y) {
  var z;
  return (z = (x * y));
};
bawbag(5, 10);

node.jsの下でcoffee-scriptを介してコンパイルすると、次のようになります。

(function() {
  var bawbag;
  bawbag = function(x, y) {
    var z;
    return (z = (x * y));
  };
  bawbag(5, 10);
}).call(this);

ドキュメントは言う:

他のスクリプトが使用するトップレベルの変数を作成したい場合は、それらをウィンドウまたはCommonJSのexportsオブジェクトにプロパティとして添付します。 CommonJSとブラウザの両方をターゲットにしている場合、存在演算子(以下で説明)を使用すると、信頼できる方法でそれらを追加する場所を見つけることができます。この

その後、CoffeeScriptでグローバル変数を定義するにはどうすればいいですか。 「ウィンドウのプロパティとしてそれらを添付する」とはどういう意味ですか?

315
Handloomweaver

Coffeeスクリプトにはvarname__ステートメントがないため、coffeeスクリプト内のすべての変数に自動的に挿入されます。これにより、コンパイルされたJavaScriptバージョンがglobal namespaceにすべてが漏れるのを防ぎます。

意図的にコーヒースクリプト側からglobal namespaceに何かを "リーク"させる方法はないので、あなたはglobal object]のプロパティとしてあなたのグローバル変数を定義する必要があります。

ウィンドウ上のプロパティとしてそれらを添付してください

global objectwindowname__なので、ブラウザのケースを扱うwindow.foo = 'baz';のようなことをする必要があります。

Node.js

Node.jsにはwindowname__オブジェクトはなく、代わりにNode.jsモジュールをラップするラッパーに渡されるexportsname__オブジェクトがあります(参照: https://github.com/ry/node/blob/master/) src/node.js#L321 )、Node.jsではexports.foo = 'baz';を実行する必要があります。

それでは、ドキュメントから引用した内容を見てみましょう。

... CommonJSとブラウザの両方をターゲットにしています:root = exports?この

これは明らかにコーヒースクリプトなので、実際にコンパイルされる内容を見てみましょう。

var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;

最初にexportsname__が定義されているかどうかをチェックします。JavaScriptで存在しない変数を参照しようとすると、そうでなければSyntaxErrorが返されるためです(typeofname__と一緒に使用する場合を除く)。

したがって、exportsname__が存在する場合、これはNode.js(または不適切に記述されたWebSite ...)の場合のように、rootはexportsname__を指し、それ以外の場合はthisname__を指します。 thisname__とは何ですか?

(function() {...}).call(this);

関数で.callを使用すると、関数内のthisname__が最初に渡されたパラメータにバインドされます。ブラウザの場合はthisname__がwindowname__オブジェクトになり、Node.jsの場合はglobal contextこれはglobalname__オブジェクトとしても利用可能です。

しかし、Node.jsにrequirename__関数があるので、Node.jsのglobalname__オブジェクトに何かを代入する必要はなく、代わりにexportsname__オブジェクトに代入します。このオブジェクトはrequirename__関数によって返されます。

コーヒースクリプト

説明が終わったら、ここであなたがする必要があるものがあります。

root = exports ? this
root.foo = -> 'Hello World'

これはグローバルネームスペースで私たちの関数fooname__を宣言します(それが何であれ)。
それで全部です :)

418
Ivo Wetzel

私には@atomiculesが最も単純な答えを持っているように見えますが、もう少し単純化できると思います。 @にコンパイルしてthisがグローバルオブジェクトを参照するように、グローバルにしたいものの前にthis.anythingを置く必要があります。

そう...

@bawbag = (x, y) ->
    z = (x * y)

bawbag(5, 10)

にコンパイル...

this.bawbag = function(x, y) {
  var z;
  return z = x * y;
};
bawbag(5, 10);

node.jsで与えられるラッパーの内側と外側で動作します。

(function() {
    this.bawbag = function(x, y) {
      var z;
      return z = x * y;
    };
    console.log(bawbag(5,13)) // works here
}).call(this);

console.log(bawbag(5,11)) // works here
57
Billy Moon

私はそれを釘付けにしました、しかし私はあなたが使うことができる1つの汚いトリックがあることに言及するでしょう、あなたがスタイルポイントのために行くなら私はそれをお勧めしません。

しかし、これが通常悪い考えである理由はここにあります:CoffeeScriptコンパイラはそれらの変数に気づいていません、それは彼らが通常のCoffeeScriptスコープ規則に従わないことを意味します。そう、

`foo = 'bar'`
foo = 'something else'

にコンパイル

foo = 'bar';
var foo = 'something else';

そして今、あなたは2つのfooを異なるスコープで持っています。 Ivyが述べたように、グローバルオブジェクトを参照せずにCoffeeScriptコードからglobalfooを変更する方法はありません。

もちろん、これはCoffeeScriptでfooに代入する場合にのみ問題になります。もし初期値が与えられた後にfooが読み取り専用になった場合(つまりグローバル定数である場合)、組み込みJavaScriptソリューションのアプローチはちょっと許容できるかもしれません。まだお勧めできませんが)。

33
Trevor Burnham

Node.jsの下のcoffee-scriptでコードをコンパイルするときに-bオプションを渡すことができます。コンパイルされたコードはcoffeescript.orgと同じものになるでしょう。

11
phongnh

私があなたが達成しようとしていることは、単純にこのようにすることができると思います:

コーヒースクリプトをコンパイルしている間は、 " - b"パラメータを使用します。

-b/--bareトップレベルの関数安全ラッパーなしでJavaScriptをコンパイルします。

だから、このようなもの:coffee -b --compile somefile.coffee whatever.js

これはCoffeeScript.orgサイトのようにあなたのコードを出力します。

9
Sankalp Singha

に追加するにはIvo Wetzelの答え

exports ? thisには、 グーグルのグループ投稿 にしか書かれていない、または言及されているものを見つけることができるという省略形の構文があるようです。

すなわちWebページで関数をグローバルに利用できるようにするには、@プレフィックスを使用して関数を再度宣言します。

<script type="text/coffeescript">
    @aglobalfunction = aglobalfunction = () ->
         alert "Hello!"
</script>

<a href="javascript:aglobalfunction()" >Click me!</a>
9
atomicules

あなたが悪い人であれば(私は悪い人です。)、あなたはこれと同じくらい簡単になることができます:(->@)()

のように、

(->@)().im_a_terrible_programmer = yes
console.log im_a_terrible_programmer

これは、ReferenceFunction 'bare'(つまり、func()またはnew func()の代わりにobj.func())に呼び出すときに、一般に「関数呼び出し呼び出しパターン」と呼ばれるものが原因で機能します。 alwaysはそのためにthisをグローバルオブジェクトにバインドします 実行コンテキスト

上記のCoffeeScriptは単に(function(){ return this })()にコンパイルします。そのため、グローバルオブジェクトに確実にアクセスするためにその動作を実行しています。

6
ELLIOTTCABLE

Coffeescriptはそれ自身ではめったに使用されないので、node.jsまたはbrowserify(およびcoffeeify、gulpビルドスクリプトなどの任意の子孫)によって提供されるglobal変数を使用できます。

Node.jsではglobalはグローバル名前空間です。

Browserifyではglobalwindowと同じです。

これだけ:

somefunc = ->
  global.variable = 123
3
metalim