Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate a CoffeeScript class from a class name in a string

Tags:

coffeescript

How do I instantiate a class in CoffeeScript when I only have the name of the class in a string?

class Dog
  bark:->
    "Woof"

className = "Dog"
dog = new className  # <--- I would like to create an instance here using the string
like image 725
Pete BD Avatar asked Jan 18 '12 15:01

Pete BD


3 Answers

With a bit of foresight you can do this pretty easily and protect yourself against using eval. Keep a list somewhere of the classes that you want to instantiate by name:

class Dog
  bark:->
    "Woof"

# Or window.named_classes if you need to access
# `named_classes` globally (or just in another
# CoffeeScript file).
named_classes = { Dog: Dog }

and then use your lookup table instead of eval:

name = 'Dog'
dog  = new named_classes[name]

When you say class Dog, you end up with a local variable called Dog:

var Dog;
Dog = (function() { /* ... */ })();

and there's no way to get at a local JavaScript variable unless you store it somewhere that you can access by name. Also note that eval won't work if you define Dog in one CoffeeScript file and want to access it another, CoffeeScript wraps each file in self-executing anonymous function to limit variable scope:

all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.

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.

like image 158
mu is too short Avatar answered Oct 19 '22 20:10

mu is too short


If using CommonJS modules then can one do something like this?

file: Dog.coffee

class Dog
  sound: ()->
    "woof"

file: Cat.coffee

class Cat
  sound: ()->
    "meow"

file: Main.coffee

className = 'Dog'
Animal = require(className)
animal = new Animal
animal.sound
# => "woof"

className = 'Cat'
Animal = require(className)
animal = new Animal
animal.sound
# => "meow"
like image 3
Pete BD Avatar answered Oct 19 '22 19:10

Pete BD


Bare in mind this isn't very good code, but I couldn't think of a better way.

Using eval:

class Dog
  bark:->
    "Woof"


className = "Dog"
dog = new (eval(classname))()

I'll keep thinking.

like image 1
Jivings Avatar answered Oct 19 '22 20:10

Jivings