Caffeine-Powered Life

Getting to Global Variables in CoffeeScript

I’m trying something in CoffeeScript this morning. Right off the bat, I need to be able to access the global window object. CoffeeScript really likes to keep it’s area nice and tidy. It does everything in its power to keep you out of the global namespace. That’s fine, right up until you need to get to the global namespace.

The answer is to add a line like this to your code.

1
root = exports ? this

Instead of accessing the window global, you will use root instead. This only makes sense when you consider that CoffeeScript is designed to be an anywhere-JavaScript framework. With tools like Node, JavaScript isn’t just for the browser any longer.

Solution

Here’s the code you need. You’ll need the line from above. And, you must explicitly add whatever you’re adding to the root object. If you do not do this, your code will be wrapped in a closure and inaccessible from your local code.

1
2
3
4
5
6
7
8
root = exports ? this

class Tester
  sayHello: (target) ->
    alert "Hello, #{target}!"

unless root.tester
  root.tester = new Tester

Here’s the result when compiled into JS. Verbose, isn’t it? Why 6 lines of CoffeeScript becomes 14 lines of JavaScript is beyond me. If I’m writing my own JavaScript classes, I typically won’t use prototyping. Not that there’s anything wrong with that. It’s just not how I would do the same thing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(function() {
  var Tester, root;

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

  Tester = (function() {

    function Tester() {}

    Tester.prototype.sayHello = function(target) {
      return alert("Hello, " + target + "!");
    };

    return Tester;

  })();

  if (!root.tester) {
    root.tester = new Tester;
  }

}).call(this);

Now you can see why using root works. When this is run in your browser, the .call(this) is passing window as the root object. Still, it all works as expect. I open this up in my browser, and all works exactly as expected.

Hope this helps. Thanks to this question and answer from StackOverflow for pointing me in the right direction.

Comments