2010-12-05 15 views
8

¿Cómo creo un nuevo objeto en javascript basado en una variable type-string (que contiene el nombre del objeto)?¿Cómo creo un nuevo objeto en javascript basado en una cadena de caracteres?

Ahora tengo: (con más herramientas que vienen de la lista se hacen más largos ...)

function getTool(name){ 
    switch(name){ 
    case "SelectTool": 
     return new SelectTool(); 
     break; 
    case "LineTool": 
     return new LineTool(); 
     break; 
    case "BlurTool": 
     return new BlurTool(); 
     break; 
    case "PointerTool": 
    default: 
     return new PointerTool(); 
     break; 
    } 
} 

y definido mis herramientas como:

PointerTool.prototype = new Tool; 
PointerTool.prototype.constructor = PointerTool; 
function PointerTool(){ 
    this.name = "PointerTool"; 
} 
PointerTool.prototype.click = function(x, y){ 
    info("You clicked at: "+x+", "+y); 
} 

me gustaría conseguir paseo de la (creciente) declaración de cambio, parece 'incorrecta'.

+0

Hipotéticamente, eval podría hacerlo ... –

+2

@ Šime Vidas, pero prácticamente, eval debe evitarse a toda costa: D –

+0

@Gabi, acepto que 'eval()' no es la solución correcta aquí, pero yo Es curioso por qué afirmas que "eval debe evitarse a toda costa". Es una característica no desaprobada del lenguaje, con usos apropiados (e inapropiados), como cualquier otra función. – Lee

Respuesta

17
function getTool(name){ 
    return (typeof window[name] === 'function') ? 
            new window[name]() : {/*some default*/}; 
} 

Asume PointerTool constructor se define en el espacio de nombres global window. Reemplace eso con el espacio de nombres que esté usando.

+1

Si está utilizando Node.js, puede usar el objeto GLOBAL para hacer lo mismo. –

+0

Iré con esta solución por ahora, olvidé por completo que _todo_es una función, por lo tanto también el objeto/funciones/espacio de nombres 'window' global :) – Dribbel

+0

@Dribbel - Suena bien. Solo usé 'ventana' porque no estaba seguro del espacio de nombres. Recomiendo definirlos en algún otro espacio de nombres si está usando 'window'. Se puede usar la misma técnica, pero si 'getTool' no está haciendo otra cosa, podrías eliminar esa llamada a la función. – user113716

8

Debería considerar replantearse su enfoque. Sería mejor tener algo así como un objeto Tools, que tendría las herramientas como las propiedades, como

Tools = {"SelectTool": SelectTool /* etc */}`. 

De esta manera, se puede acceder a las herramientas tanto como new Tools.SelectTool y new Tools[var_with_tool_name].

+0

Esto me parece más complicado que el enfoque de Patrick. –

+2

Sí, pero funciona incluso si las herramientas están en espacios de nombres diferentes. –

3

En su ejemplo, declara PointerTool como una función en el ámbito global. Suponiendo que su javascript ejecuta el navegador, el "alcance global" es en realidad igual que el objeto window. Eso significa que si usted tiene un constructor:

function PointerTool() { 
    ... 
} 

que es lo mismo que esto:

window.PointerTool = function() { 
    ... 
} 

Así que ahora, en su función de getTool, puede acceder a sus funciones constructoras como esto:

function getTool(name){ 
    return new window[name](); 
} 

Una manera más "a prueba de futuro" de hacer esto sería definir su propio objeto de espacio de nombres, en el que se pla ce todos sus diversos constructores de herramientas. Algo como esto ("miproyecto" sería el nombre corto de su proyecto o sistema):

var myproject = { tools: {} }; 

// Pointer Tool Constructor 
myproject.tools.PointerTool = function() { 
    ... 
} 

// Line Tool Constructor 
myproject.tools.LineTool = function() { 
    ... 
} 

// and so on 

Luego, su función getTool se vería así:

function getTool(name){ 
    return new myproject.tools[name](); 
} 

Este enfoque mantiene su material aislado de cualquier otras cosas se definen en el ámbito global/ventana.

+0

No, 'function PointerTool' ≠' window.PointerTool = function': la primera es una función * declaration *, la segunda es una función * expression *. http://kangax.github.com/nfe/#expr-vs-decl –

+0

Es cierto, pero en el contexto de esta pregunta, es lo suficientemente igual. Es decir, puede hacer referencia a 'PointerTool' utilizando' window.PointerTool', que es el punto de esta respuesta. – MooGoo

Cuestiones relacionadas