Daniel Kaplan
Daniel Kaplan

Reputation: 67440

In CoffeeScript, how can I filter out a global array without accidentally declaring it?

I'm pretty new to CoffeeScript, and I've been reading this book. There's a section called Select that talks about using your typical functional programming filter function. It says you can do it like this:

attacks = (attack for attack in attacks when attack is "a")

The intent is to filter out all the elements that don't equal "a". This works fine, as long as attacks is declared in the same file. But, if I've got attacks declared in another file, like so:

attacks = ["a", "b"]
root = exports ? this
root.attacks = attacks

Then the first code gets compiled like this:

function() {
    var attack, attacks, _i, _len;
    ...

And you'll get an error on the for loop saying

TypeError: attacks is undefined

This is happening, I guess, because CoffeeScript sees something on the left hand side of an = it doesn't know about and decides it needs to be declared.

How can I avoid this?


Actually, I've already figured out one method. And that is to modify the first snippet to say this:

root.attacks = (attack for attack in attacks when attack is "a")

Is this a good solution?

Upvotes: 1

Views: 175

Answers (2)

Brandon
Brandon

Reputation: 3524

Coffeescript will use the global "window" if you explicitly tell it to. I would be hesitant to start assigning properties directly to window if I were you. At the very least you could put them all into one object on window like: window.globals = window.globals ? {} then window.globals.attacks = (attack for attack in attacks when attack is "a"). For a more robust solution you could consider something like the following:

window['moduleName'] = (->
  someOtherVariableToExpose = 'something'
  # All of your code

  attacks: attacks
  anotherThing: someOtherVariableToExpose)()

In javascript this looks like:

window['moduleName'] = (function() {
  var someOtherVariableToExpose;
  var attacks;

  someOtherVariableToExpose = 'something';
  attacks = 'whatever your code defined it as';
  return {
    attacks: attacks,
    anotherThing: someOtherVariableToExpose
  };
})();

This creates a nice little closure around all of this file's private code and only exposes window['moduleName'].attacks, and window['moduleName'].anotherThing.

If your app will grow large you could look into module dependency libraries such as requirejs or browserify

Edited To make sure the anonymous function was called immediately so the returned object really is all that is exposed.

Upvotes: 1

Ben McCormick
Ben McCormick

Reputation: 25728

Yes your solution is a good solution. Coffeescript will create a local variable for your references if you're not pulling them in from somewhere else explicitly so you need to do that. If you know that this code is in node or in the browser you can be more explicit and say window.attacks or require() the file that contains attacks and grab it that way. If its intended to be shared then your solution is a good one.

Upvotes: 1

Related Questions