2012-01-18 16 views

risposta

11

Con un po 'di previsione, è possibile farlo abbastanza facilmente e proteggersi dall'utilizzo di eval. Tenere un elenco da qualche parte delle classi che si desidera creare un'istanza per nome:

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 } 

e quindi utilizzare il tabella di ricerca, invece di eval:

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

Quando si dice class Dog, si finisce con un locale variabile chiamata Dog:

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

e non c'è modo di arrivare a una variabile JavaScript locale a meno di riporlo somewher e a cui è possibile accedere per nome. Si noti inoltre che eval non funziona se si definisce Dog in un unico file CoffeeScript e desidera accedere in un altro, CoffeeScript wraps each file in self-executing anonymous function to limit variable scope:

tutto l'output CoffeeScript è avvolto in una funzione anonima: (function(){ ... })(); Questo involucro di sicurezza, combinato con la generazione automatica della parola chiave var, rende estremamente difficile inquinare il namespace globale per sbaglio.

Se vuoi creare variabili di primo livello per altri script da utilizzare, fissarli come proprietà su finestra, o sulla esportazioni oggetto in CommonJS.

+2

Per aggiungere a quello, piuttosto che raccoglierli dopo il fatto, si potrebbe trovare più conveniente per lo spazio dei nomi per iniziare. Da qualche parte prima di tutto: 'myClasses = {}' seguito: 'classe myClasses.Dog' Infine:' cane = new myClasses [ "Dog"] ' –

+0

@ Chris: Sì, questo è un buon punto. Si potrebbe usare 'class window.Dog' o' class window.named_classes.Dog' ma 'window.Dog' rischia di inquinare' window' e 'window.named_classes.Dog' rende l'accesso locale a' Dog' un po 'macchinoso. Si potrebbe anche fare 'named_classes.Dog = class Dog ...' ma questo è, IMO, un po 'brutto. –

+0

@Chris: sembra che stiamo modificando i commenti allo stesso tempo (e la mia connessione Internet è dubbia!). Comunque, ci sono vari modi per ottenere l'effetto desiderato, l'importante è memorizzare un riferimento alla classe in un oggetto da qualche parte in modo che abbia un nome accessibile dal programma. –

1

Bare in mente questo non è molto buon codice, ma non riuscivo a pensare a un modo migliore.

Utilizzando eval:

class Dog 
    bark:-> 
    "Woof" 


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

io continuo a pensare.

+0

Sì, ho pensato a questo ma speravo ci sarebbe un metodo più attraente. –

+0

Giù vota per una chiamata molto inutile alla valutazione. Evita la valutazione mu ha la risposta giusta qui. –

+0

@ChrisSubagio Ho detto che non era una buona idea, non potevo pensare a una migliore. – Jivings

3

Se si utilizzano i moduli CommonJS, allora si può fare qualcosa di simile?

di file: Dog.coffee

class Dog 
    sound:()-> 
    "woof" 

di file: file di Cat.coffee

class Cat 
    sound:()-> 
    "meow" 

: Main.coffee

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

className = 'Cat' 
Animal = require(className) 
animal = new Animal 
animal.sound 
# => "meow" 
0

ne dici di questo?

dog.coffee

class Dog 
    bark:-> 
    "Woof" 

app.coffee

@Dog = require './dog' 
className = "Dog" 
dog = new @[className] 
+0

Ciò equivale a: classe @Dog corteccia: -> "bau" className = 'Dog' cane = new questo [className] avviso dog.bark() –

Problemi correlati