316

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);

ドキュメントは言う:

他のスクリプトで使用する最上位の変数を作成する場合は、window のプロパティとして、または CommonJS の exports オブジェクトにそれらをアタッチします。CommonJS とブラウザーの両方をターゲットにしている場合、存在演算子 (以下で説明) を使用すると、それらを追加する場所を特定する信頼できる方法が得られます: root = exports ? これ

次にCoffeeScriptでグローバル変数を定義するにはどうすればよいですか。「ウィンドウのプロパティとしてアタッチする」とはどういう意味ですか?

4

9 に答える 9

418

coffee スクリプトにはステートメントがないvarため、coffee-script のすべての変数に対してステートメントが自動的に挿入されます。これにより、コンパイルされた JavaScript バージョンがグローバルな名前空間にすべてをリークするのを防ぐことができます。

そのため、コーヒー スクリプト側から意図的に何かをグローバル名前空間に「リーク」させる方法はないため、グローバル変数をグローバル オブジェクトのプロパティとして定義する必要があります。

それらをウィンドウのプロパティとして添付します

これはwindow.foo = 'baz';グローバル オブジェクトwindow.

Node.js

Node.js にはwindowオブジェクトはありません。代わりにexports、Node.js モジュールをラップするラッパーに渡されるオブジェクトがあります (参照: 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;

最初にexportsが定義されているかどうかを確認します。JavaScript で存在しない変数を参照しようとすると SyntaxError が発生するためです ( で使用されている場合を除くtypeof) 。

exports存在する場合は、Node.js (または不適切に記述された Web サイトの場合) の場合、ルートは を指しexports、そうでない場合はを指しthisます。それで、何thisですか?

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

関数で使用すると、渡された最初のパラメーターに関数内.callがバインドされます。ブラウザーの場合はオブジェクトになり、Node.js の場合は、オブジェクトとしても使用できるグローバル コンテキストになります。 thisthiswindowglobal

ただし、requireNode.js に関数があるため、Node.js のオブジェクトに何かを割り当てる必要はありませんglobal。代わりに、関数exportsによって返されるオブジェクトに割り当てます。require

コーヒースクリプト

すべての説明の後、次のことを行う必要があります。

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

fooこれにより、関数がグローバル名前空間で宣言されます (それが何であれ)。
それで全部です :)

于 2010-11-18T13:16:20.257 に答える
59

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

それで...

@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
于 2012-06-29T12:53:17.587 に答える
33

Ivoはそれを釘付けにしましたが、使用できる汚いトリックが1つあることを述べておきますが、スタイルポイントを求める場合はお勧めしません。バックティックでエスケープすることで、JavaScriptコードをCoffeeScriptに直接埋め込むことができます。

ただし、これが通常は悪い考えである理由は次のとおりです。CoffeeScriptコンパイラはこれらの変数を認識しません。つまり、通常のCoffeeScriptスコープルールに従わないということです。それで、

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

にコンパイルします

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

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

もちろん、これはfooCoffeeScriptで割り当てを行う場合にのみ問題fooになります。初期値が与えられた後に読み取り専用になった場合(つまり、グローバル定数)、埋め込まれたJavaScriptソリューションのアプローチはある程度受け入れられる可能性があります(それでも推奨されません)。

于 2010-11-20T05:07:17.443 に答える
11

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

于 2011-08-27T06:49:15.220 に答える
9

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

Google グループの投稿exports ? thisでのみ文書化/言及されているのを見つけることができる省略形の構文があるようです。

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

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

<a href="javascript:aglobalfunction()" >Click me!</a>
于 2011-09-14T09:40:39.497 に答える
7

あなたが悪い人なら (私は悪い人です)、次のように簡単に取得できます。(->@)()

のように、

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

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

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

于 2015-12-19T03:51:05.743 に答える