Как определить глобальные переменные в CoffeeScript? - PullRequest
315 голосов
/ 18 ноября 2010

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

компиляция с помощью coffee-script в node.js оборачивается так:

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

Документы говорят:

Если вы хотите создать переменные верхнего уровня для использования другими сценариями, прикрепить их как свойства к окну или к объекту экспорта в CommonJS. Экзистенциальный оператор (описан ниже), дает вам надежный способ выяснить, где их добавить, если вы ориентируетесь как на CommonJS и браузер: root = экспорт? это

Как определить глобальные переменные затем в CoffeeScript. Что означает «прикрепить их как свойства к окну»?

Ответы [ 8 ]

418 голосов
/ 18 ноября 2010

Поскольку в сценарии кофе нет оператора var, он автоматически вставляет его для всех переменных в сценарии кофе, что предотвращает утечку скомпилированной версии JavaScript в глобальное пространство имен .

Таким образом, поскольку невозможно что-то «просочиться» в глобальное пространство имен со стороны сценариев «кофе» специально, вам необходимо определить глобальные переменные как свойства global объект .

прикрепить их как свойства к окну

Это означает, что вам нужно сделать что-то вроде 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 = export? это

Это, очевидно, кофейный скрипт, так что давайте посмотрим, к чему это на самом деле компилируется:

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

Сначала он проверит, определено ли exports, поскольку попытка ссылки на несуществующую переменную в JavaScript в противном случае приведет к ошибке SyntaxError (кроме случаев, когда она используется с typeof)

Таким образом, если существует exports, что имеет место в корне Node.js (или в плохо написанном веб-сайте ...), он будет указывать на exports, иначе на this. Так что же такое this?

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

Использование .call в функции привяжет this внутри функции к первому переданному параметру, в случае браузера this теперь будет объектом window, в случае Node.js это будет быть глобальным контекстом , который также доступен как объект global.

Но так как у вас есть функция require в Node.js, нет необходимости назначать что-либо объекту global в Node.js, вместо этого вы присваиваете объекту exports, который затем возвращается require функция.

Кофе-Script

После всего этого объяснения вот что вам нужно сделать:

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

Это объявит нашу функцию foo в глобальном пространстве имен (что бы это ни было).
Вот и все:)

57 голосов
/ 29 июня 2012

Мне кажется, @atomicules имеет самый простой ответ, но я думаю, что его можно упростить немного больше. Вам нужно поставить @ перед тем, что вы хотите сделать глобальным, чтобы оно компилировалось в this.anything, а this относится к глобальному объекту.

так ...

@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
33 голосов
/ 20 ноября 2010

Ivo прибил его, но я упомяну, что есть один грязный трюк, который вы можете использовать, хотя я не рекомендую его, если вы работаете с точками стиля: вы можете встраивать код JavaScript прямо в ваш CoffeeScript, избегая егос обратными галочками.

Однако вот почему это обычно плохая идея: компилятор CoffeeScript не знает об этих переменных, что означает, что они не будут подчиняться нормальным правилам области действия CoffeeScript.Итак,

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

компилируется в

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

, и теперь у вас есть две foo в разных областях.Как описал Айви, нет способа изменить global foo из кода CoffeeScript без ссылки на глобальный объект.

Конечно, это проблема, только если вы делаете присвоение foo в CoffeeScript - если foo стал доступным только для чтения после получения его начального значения (т. Е. Глобальной константы), то подход к встроенному решению JavaScript может быть своего рода приемлемым (хотя все еще не рекомендуется).

11 голосов
/ 27 августа 2011

Вы можете передать опцию -b, когда компилируете код с помощью coffee-script в файле node.js. Скомпилированный код будет таким же, как на coffeescript.org.

9 голосов
/ 13 февраля 2014

Я думаю, что вы пытаетесь достичь, можно просто сделать так:

Во время компиляции coffeescript используйте параметр "-b".

-b / --bare Скомпилируйте JavaScript без использования защитной оболочки функции верхнего уровня.

Примерно так: coffee -b --compile somefile.coffee whatever.js

Это выведет ваш код, как в CoffeeScript..org site.

9 голосов
/ 14 сентября 2011

Добавить к ответ Иво Ветцеля

Кажется, что для exports ? this существует сокращенный синтаксис, который я могу найти только документированным / упомянутым в публикации группы Google .

т.е. на веб-странице, чтобы сделать функцию доступной глобально, вы снова объявляете функцию с префиксом @:

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

<a href="javascript:aglobalfunction()" >Click me!</a>
6 голосов
/ 19 декабря 2015

Если вы плохой человек (я плохой человек), вы можете получить так просто: (->@)()

Как,

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

Это работает, потому что при вызове Reference к Function «голому» (то есть func() вместо new func() или obj.func()), что обычно называют «вызовом функции»pattern ', всегда связывает this с глобальным объектом для этого контекста исполнения .

Приведенный выше CoffeeScript просто компилируется в (function(){ return this })();поэтому мы используем это поведение для надежного доступа к глобальному объекту.

3 голосов
/ 03 октября 2016

Поскольку coffeescript редко используется сам по себе, вы можете использовать переменную global, предоставляемую либо node.js, либо browserify (и любыми потомками, такими как coffeeify, сценарии сборки gulp и т. Д.).

В node.js global - это глобальное пространство имен.

В browserify global равно window.

Итак, просто:

somefunc = ->
  global.variable = 123
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...