Sur Coffeescript.org:
bawbag = (x, y) ->
z = (x * y)
bawbag(5, 10)
compilerait pour:
var bawbag;
bawbag = function(x, y) {
var z;
return (z = (x * y));
};
bawbag(5, 10);
la compilation via coffee-script sous node.js enveloppe ainsi:
(function() {
var bawbag;
bawbag = function(x, y) {
var z;
return (z = (x * y));
};
bawbag(5, 10);
}).call(this);
Les docs disent:
Si vous souhaitez créer des variables de niveau supérieur que d'autres scripts peuvent utiliser, attachez-les en tant que propriétés dans window ou sur l'objet exports dans CommonJS. L'opérateur existentiel (décrit ci-dessous) vous donne un moyen fiable de déterminer où les ajouter, si vous ciblez à la fois CommonJS et le navigateur: root = exports? cette
Comment définir des variables globales dans CoffeeScript? Que signifie "attachez-les en tant que propriétés sur une fenêtre"?
Comme le script coffee n’a pas d’instruction var
, il l’insère automatiquement pour toutes les variables du script coffee-script, ce qui empêche la version JavaScript compilée de fuir dans le namespace global .
Donc, puisqu'il n'y a aucun moyen de faire quelque chose de "fuite" dans l'espace de noms global du côté café-script des choses à dessein, vous devez définir votre global variables en tant que propriétés de l'objet global .
attachez-les comme propriétés sur la fenêtre
Cela signifie que vous devez faire quelque chose comme window.foo = 'baz';
, qui gère la casse du navigateur, car l'objet global est le window
.
Dans Node.js, il n'y a pas d'objet window
, mais plutôt l'objet exports
qui est transmis au wrapper qui encapsule le module Node.js (voir: https://github.com/ ry/node/blob/maître/src/node.js # L321 ), donc dans Node.js, vous devez faire exports.foo = 'baz';
.
Voyons maintenant ce qui est écrit dans votre citation de la documentation:
... ciblant à la fois CommonJS et le navigateur: root = exports? cette
Ceci est évidemment un script de café, alors jetons un coup d'oeil à ce que cela compile réellement pour:
var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;
Tout d'abord, il vérifiera si exports
est défini, car essayer de référencer une variable inexistante dans JavaScript produirait sinon une SyntaxError (sauf si elle est utilisée avec typeof
)
Donc, si exports
existe, ce qui est le cas dans Node.js (ou dans un site Web mal écrit ...), la racine pointera sur exports
, sinon this
. Alors qu'est-ce que this
?
(function() {...}).call(this);
Utiliser .call
sur une fonction liera le this
de la fonction au premier paramètre transmis, dans le cas où le navigateur this
serait désormais l'objet window
, dans le cas de Node.js ce serait le contexte global qui est également disponible en tant qu'objet global
.
Mais puisque vous avez la fonction require
dans Node.js, il n’est pas nécessaire d’attribuer quelque chose à l’objet global
dans Node.js, mais vous affectez à l’objet exports
qui est ensuite renvoyé. par la fonction require
.
Après toutes ces explications, voici ce que vous devez faire:
root = exports ? this
root.foo = -> 'Hello World'
Cela déclarera notre fonction foo
dans l’espace de noms global (quel qu’il soit).
C'est tout :)
Il me semble que @atomicules a la réponse la plus simple, mais je pense que cela peut être simplifié un peu plus. Vous devez placer un @
avant tout élément que vous voulez être global, afin qu'il soit compilé en this.anything
et this
se réfère à l'objet global.
@bawbag = (x, y) ->
z = (x * y)
bawbag(5, 10)
this.bawbag = function(x, y) {
var z;
return z = x * y;
};
bawbag(5, 10);
(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
Ivo a réussi, mais je mentionnerai qu'il existe un mauvais tour que vous pouvez utiliser, bien que je ne le recommande pas si vous recherchez des points de style: vous pouvez incorporer du code JavaScript directement dans votre CoffeeScript en lui échappant avec des backticks.
Cependant, voici pourquoi c'est généralement une mauvaise idée: le compilateur CoffeeScript n'est pas au courant de ces variables, ce qui signifie qu'elles n'obéiront pas aux règles de portée de CoffeeScript normales. Alors,
`foo = 'bar'`
foo = 'something else'
compile pour
foo = 'bar';
var foo = 'something else';
et maintenant vous avez vous-même deux foo
s dans différentes portées. Il n'y a aucun moyen de modifier le code globalfoo
à partir du code CoffeeScript sans faire référence à l'objet global, comme décrit par Ivy.
Bien sûr, ce n’est un problème que si vous faites une assignation à foo
dans CoffeeScript — si foo
est devenu en lecture seule après avoir reçu sa valeur initiale (c’est-à-dire qu’il s’agit d’une constante globale), le code JavaScript intégré L’approche de la solution pourrait être un peu acceptable (bien que cela ne soit toujours pas recommandé).
Vous pouvez passer l'option -b lorsque vous compilez du code via coffee-script sous node.js. Le code compilé sera le même que sur coffeescript.org.
Je pense que ce que vous essayez de réaliser peut simplement être fait comme ceci:
Pendant la compilation du coffeescript, utilisez le paramètre "-b".
-b
/--bare
Compilez le code JavaScript sans le wrapper de sécurité de fonction de niveau supérieur.
Donc, quelque chose comme ceci: coffee -b --compile somefile.coffee whatever.js
Cela produira votre code comme sur le site CoffeeScript.org.
Pour ajouter à réponse d'Ivo Wetzel
Il semble exister une syntaxe abrégée pour exports ? this
que je ne trouve que documentée/mentionnée sur un publication de groupe Google .
C'est à dire. dans une page Web pour rendre une fonction disponible globalement, vous déclarez à nouveau la fonction avec le préfixe @
:
<script type="text/coffeescript">
@aglobalfunction = aglobalfunction = () ->
alert "Hello!"
</script>
<a href="javascript:aglobalfunction()" >Click me!</a>
Si vous êtes une mauvaise personne (je suis une mauvaise personne.), Vous pouvez obtenir aussi simple que ceci: (->@)()
Un péché,
(->@)().im_a_terrible_programmer = yes
console.log im_a_terrible_programmer
Cela fonctionne car, lorsqu’on invoque une Reference
sur une Function
'bare' (c’est-à-dire func()
, au lieu de new func()
ou obj.func()
, généralement appelée En tant que 'modèle d'appel d'appel de fonction', toujours lie this
à l'objet global pour cela contexte d'exécution =.
Le CoffeeScript ci-dessus se compile simplement en (function(){ return this })()
; Nous exerçons donc ce comportement pour accéder de manière fiable à l'objet global.
Coffeescript étant rarement utilisé seul, vous pouvez utiliser la variable global
fournie par node.js ou par browserify (ainsi que par tous les descendants tels que coffeeify, gulp build scripts, etc.).
Dans node.js global
est un espace de noms global.
Dans browserify global
est égal à window
.
Alors, juste:
somefunc = ->
global.variable = 123