web-dev-qa-db-fra.com

Comment définir des variables globales dans CoffeeScript?

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"?

317
Handloomweaver

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 .

Node.js

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.

Café-Script

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

419
Ivo Wetzel

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.

alors...

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

bawbag(5, 10)

compile pour ...

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

et travaille à l'intérieur et à l'extérieur du wrapper donné par 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

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 foos 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é).

33
Trevor Burnham

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.

11
phongnh

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/--bareCompilez 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.

9
Sankalp Singha

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>
9
atomicules

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.

7
ELLIOTTCABLE

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
3
metalim