Jak zdefiniować zmienne globalne w CoffeeScript?

On Coffeescript.org:

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

bawbag(5, 10) 

Skompiluje się do:

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

Kompilowanie przez coffee-script pod węzłem.js owija to tak:

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

Docs says:

Jeśli chcesz utworzyć zmienne najwyższego poziomu dla innych skryptów, załączyć je jako właściwości w oknie lub na obiekcie exports w CommonJS. Operatorem egzystencjalnym (omówionym poniżej), daje niezawodny sposób, aby dowiedzieć się, gdzie je dodać, jeśli kierujesz oba CommonJS i przeglądarka: root = eksport ? this

Jak zdefiniować zmienne globalne w CoffeeScript. Co oznacza "załącz je jako właściwości w oknie"?

Author: sam, 2010-11-18

8 answers

Ponieważ skrypt coffee nie ma instrukcji var, automatycznie wstawia ją dla wszystkich zmiennych w skrypcie coffee-script, dzięki czemu skompilowana wersja JavaScript nie wycieka wszystkiego doglobalnej przestrzeni nazw .

Więc ponieważ nie ma sposobu, aby coś "wyciekło" do globalnej przestrzeni nazw od strony skryptów kawowych celowo, musisz zdefiniować swoje zmienne globalne jako właściwości globalnego obiektu .

Dołącz je jako właściwości w oknie

Oznacza to, że musisz zrobić coś w rodzaju window.foo = 'baz';, który obsługuje sprawę przeglądarki, ponieważ tam global object jest window.

Węzeł.js

W Węźle.js nie ma window obiektu, zamiast tego jest exports obiekt, który jest przekazywany do owijarki, która owija węzeł.moduł js (Zobacz: https://github.com/ry/node/blob/master/src/node.js#L321 ), więc w węźle.js to co musisz zrobić to exports.foo = 'baz';.

Teraz spójrzmy, co stwierdza w cytacie z dokumentów:

...targeting both CommonJS and the browser: root = exports ? to

Jest to oczywiście skrypt kawowy, więc przyjrzyjmy się temu, do czego właściwie się składa:]}
var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;

Najpierw sprawdzi, czy exports jest zdefiniowana, ponieważ próba odwołania się do nieistniejącej zmiennej w JavaScript w przeciwnym razie spowodowałaby błąd SyntaxError (z wyjątkiem sytuacji, gdy jest używany z typeof)

Więc jeśli exports istnieje, co ma miejsce w Node.js (lub w źle napisanej witrynie...) root będzie wskazywał na exports, inaczej na this. Więc co to jest this?

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

Użycie .call na funkcji spowoduje powiązanie this wewnątrz funkcji z pierwszym przekazanym parametrem, w przypadku przeglądarki this będzie teraz obiektem window, W przypadku węzła.js będzie to kontekst globalny, który jest również dostępny jako obiekt global.

Ale skoro masz require funkcja w węźle.js, nie ma potrzeby przypisywania czegoś do global obiektu w Node.js, zamiast tego przypisujesz obiekt exports, który następnie jest zwracany przez funkcję require.

Coffee-Script

Po tym wszystkim wyjaśnieniu, oto co musisz zrobić:

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

To zadeklaruje naszą funkcję foo w globalnej przestrzeni nazw (cokolwiek to się stanie).
To wszystko:)

 417
Author: Ivo Wetzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-29 02:59:24

Wydaje mi się, że @atomicules ma najprostszą odpowiedź, ale myślę, że można ją nieco uprościć. Musisz umieścić @ przed wszystkim, co chcesz być globalne, tak, że kompiluje się do this.anything i this odnosi się do obiektu globalnego.

Więc...

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

bawbag(5, 10)

Kompiluje do...

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

I działa wewnątrz i na zewnątrz opakowania podanego przez 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
Author: Billy Moon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-29 12:53:17

Ivo udało się, ale wspomnę, że jest jedna brudna sztuczka, której możesz użyć, choć nie polecam jej, jeśli chodzi o style points: możesz osadzać kod JavaScript bezpośrednio w CoffeeScript, uciekając go za pomocą backticks.

Jednakże, oto dlaczego jest to zazwyczaj zły pomysł: kompilator CoffeeScript nie jest świadomy tych zmiennych, co oznacza, że nie będą przestrzegać normalnych reguł coffeescript scoping rules. Więc

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

Kompiluje do

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

And now you ' ve got yourself two fooS w różnych zakresach. Nie ma możliwości modyfikacji globalnego foo z kodu CoffeeScript bez odwoływania się do obiektu globalnego, jak opisano w Ivy.

Oczywiście, jest to tylko problem, jeśli przyporządkujesz foo w CoffeeScript-jeśli foo stało się tylko do odczytu po podaniu jej wartości początkowej( tzn. jest to stała globalna), to osadzone rozwiązanie JavaScript może być w pewnym sensie akceptowalne (choć nadal nie jest zalecane).

 33
Author: Trevor Burnham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-20 05:07:17

Możesz przekazać opcję-b podczas kompilacji kodu przez coffee-script pod węzłem.js. Skompilowany kod będzie taki sam jak na coffeescript.org.

 11
Author: phongnh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-27 06:49:15

Aby dodać do odpowiedź Ivo Wetzela

Wydaje się, że istnieje skrócona składnia exports ? this, którą mogę znaleźć tylko udokumentowaną/wspomnianą na Google Group posting.

Tzn. na stronie internetowej, aby funkcja była dostępna globalnie, deklarujesz funkcję ponownie za pomocą prefiksu @:

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

<a href="javascript:aglobalfunction()" >Click me!</a>
 9
Author: atomicules,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:26

Myślę, że to, co próbujesz osiągnąć, można po prostu zrobić tak:

Podczas kompilacji coffeescript użyj parametru "- b".

-b / --bare skompilować JavaScript bez najwyższego poziomu funkcji safety wrapper.

Więc coś takiego: coffee -b --compile somefile.coffee whatever.js

To wyświetli Twój kod tak jak w CoffeeScript.org miejscu.

 9
Author: Sankalp Singha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-14 16:16:56

Jeśli jesteś złą osobą (jestem złą osobą.), można uzyskać tak proste jak to: (->@)()

Jak w,

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

Działa to, ponieważ gdy wywołujemy Reference do Function 'nagie' (to znaczy func(), zamiast new func() lub obj.func()), coś powszechnie określane jako 'wzorzec wywołania funkcji', zawsze wiąże this z obiektem globalnym dla tego kontekstu wykonania .

Powyższy CoffeeScript po prostu kompiluje się do (function(){ return this })(); więc ćwiczymy to zachowanie niezawodny dostęp do globalnego obiektu.

 6
Author: ELLIOTTCABLE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-19 03:51:05

Ponieważ coffeescript jest rzadko używany samodzielnie, możesz użyć zmiennej global dostarczanej przez dowolny węzeł.js lub browserify (i wszelkie potomkinie, takie jak coffeeify, gulp build scripts itp.).

W węźle.js global jest globalną przestrzenią nazw.

W browserify {[1] } jest równe window.

Więc, po prostu:

somefunc = ->
  global.variable = 123
 3
Author: metalim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-03 12:04:53