[javascript] How do I define global variables in CoffeeScript?

On Coffeescript.org:

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

bawbag(5, 10) 

would compile to:

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

compiling via coffee-script under node.js wraps that so:

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

Docs say:

If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them, if you're targeting both CommonJS and the browser: root = exports ? this

How do I define Global Variables then in CoffeeScript. What does 'attach them as properties on window' mean?

This question is related to javascript coffeescript

The answer is


I think what you are trying to achieve can simply be done like this :

While you are compiling the coffeescript, use the "-b" parameter.

-b / --bare Compile the JavaScript without the top-level function safety wrapper.

So something like this : coffee -b --compile somefile.coffee whatever.js

This will output your code just like in the CoffeeScript.org site.


Ivo nailed it, but I'll mention that there is one dirty trick you can use, though I don't recommend it if you're going for style points: You can embed JavaScript code directly in your CoffeeScript by escaping it with backticks.

However, here's why this is usually a bad idea: The CoffeeScript compiler is unaware of those variables, which means they won't obey normal CoffeeScript scoping rules. So,

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

compiles to

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

and now you've got yourself two foos in different scopes. There's no way to modify the global foo from CoffeeScript code without referencing the global object, as Ivy described.

Of course, this is only a problem if you make an assignment to foo in CoffeeScript—if foo became read-only after being given its initial value (i.e. it's a global constant), then the embedded JavaScript solution approach might be kinda sorta acceptable (though still not recommended).


You can pass -b option when you compile code via coffee-script under node.js. The compiled code will be the same as on coffeescript.org.


If you're a bad person (I'm a bad person.), you can get as simple as this: (->@)()

As in,

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

This works, because when invoking a Reference to a Function ‘bare’ (that is, func(), instead of new func() or obj.func()), something commonly referred to as the ‘function-call invocation pattern’, always binds this to the global object for that execution context.

The CoffeeScript above simply compiles to (function(){ return this })(); so we're exercising that behavior to reliably access the global object.


To add to Ivo Wetzel's answer

There seems to be a shorthand syntax for exports ? this that I can only find documented/mentioned on a Google group posting.

I.e. in a web page to make a function available globally you declare the function again with an @ prefix:

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

<a href="javascript:aglobalfunction()" >Click me!</a>

To me it seems @atomicules has the simplest answer, but I think it can be simplified a little more. You need to put an @ before anything you want to be global, so that it compiles to this.anything and this refers to the global object.

so...

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

bawbag(5, 10)

compiles to...

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

and works inside and outside of the wrapper given by 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

Since coffeescript is rarely used on it's own, you can use global variable supplied by either node.js or browserify (and any descendants like coffeeify, gulp build scripts, etc).

In node.js global is global namespace.

In browserify global is equal to window.

So, just:

somefunc = ->
  global.variable = 123