LandonSchropp
LandonSchropp

Reputation: 10274

Extending a CoffeeScript class dynamically

I know that a CoffeeScript class can be extended like this:

Dog::bark = ->
  console.log("bark")

I want to be able to do this dynamically. For example, I want to do something like this:

sounds = [ "bark", "woof", "grrr", "ruff" ] 

for sound in sounds
  Dog::[sound] = ->
    console.log(sound)

The equivalent JavaScript would be:

var sounds = [ "bark", "woof", "grrr", "ruff" ];

for (var i = 0; i < sounds.length; i++) 
{
  var sound = sounds[i];

  Dog.prototype[sound] = function() {
    console.log(sound);
  };
}

How can I do this with CoffeeScript?

Upvotes: 2

Views: 488

Answers (1)

mu is too short
mu is too short

Reputation: 434985

You almost have it, you just need to toss a do in there to force sound to be evaluated when you build the new method:

sounds = [ "bark", "woof", "grrr", "ruff" ] 
for sound in sounds
    do (sound) ->
        Dog::[sound] = -> console.log(sound)

If you don't include the do you'll end up with all four methods doing console.log('ruff'). Adding the do converts the for loop's body to a self-executing function. From the fine manual (bottom of the section):

When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.

Demo: http://jsfiddle.net/ambiguous/YAqJu/

Upvotes: 4

Related Questions