11
votes

Comment créer un nouvel objet dans JavaScript en fonction d'une chaîne de type?

Comment créer un nouvel objet en JavaScript en fonction d'une chaîne de type variable (contenant le nom de l'objet)?

Maintenant, j'ai: (Avec plus d'outils à venir, la liste deviendra plus longtemps ...) < / p> xxx

et défini mes outils tels que: xxx

Je voudrais obtenir la conduite de la déclaration de commutation (en croissance), semble "faux".


13 commentaires

Hypothétiquement, eval pourrait le faire ...


@ Šime Vidas, mais pratiquement, l'évaluation doit être évitée à tout prix: D


@Gabi, je suis d'accord que eval () n'est pas la solution correcte ici, mais je suis curieux pourquoi vous affirmez que "eval devrait être évité à tout prix". C'est une caractéristique non obsolète de la langue, avec des utilisations appropriées (et inappropriées) - comme toutes les autres caractéristiques.


@ Šime: Je vais demander à Jeff à ajouter des bowvotes sur les commentaires! :-P


@Lee je n'ai pas dit ça. Gabi l'a dit.


@Gabi Purcaru: Dans ce cas, l'utilisation de l'évaluation est appropriée. Cependant, j'aimerais créer des outils et faire si (str_tool in tools) obj_tool = nouveaux outils [str_tool]


@Lee, mais d'après ce que je comprends, l'utilisation de EVAL limite les minificateurs des noms de variables de raccourcissement. Donc, il est en fait valable de dire «N'utilisez jamais Eval».


@Lee je me considère assez maladroit pour faire une erreur stupide à l'aide d'outils dangereux, alors je l'évite à tout prix.


@Gabi: assez juste. Tous les codeurs efficaces définissent "les règles personnelles pour coder" ... J'ai beaucoup de mienne.


Parfois, eval est la seule réponse, et c'est quand il doit être utilisé. Si ces objets ont été définis dans une fonction d'exécution auto anonyme, ils n'ont pas pu être référencés à l'aide de la fenêtre [constructeur] .


Whoa! Ma question est-elle simplement devenue un petit ev i al flamme-guerre :)


@MOOGOO: Dans ce cas, je définirais un objet dans l'espace de noms de cette fonction anonyme auto-invoquant avec les fonctions que je veux appeler ainsi comme propriétés de cet objet. Ensuite, vous pouvez toujours utiliser TooObject [modeName] .


Il y a toujours une autre façon bien sûr. Presque n'importe quel code peut être écrit de manière à éviter les évaluations. Cependant, l'EVAL peut souvent faire fonctionner avec le code existant plus facile sans la nécessité de refracteur. Ce n'est pas Soooo Eeevvilll que vous devriez réécrire la moitié de votre code de merde juste pour l'éviter, tant que vous gardez à l'esprit la «meilleure» façon de faire des choses à l'avenir.


3 Réponses :


19
votes
function getTool(name){
  return ( typeof window[name] === 'function' ) ? 
                                    new window[name]() : {/*some default*/};
}
Assumes PointerTool constructor is defined in the global window namespace. Replace that with whatever namespace you're using.

3 commentaires

Si vous utilisez node.js, vous pouvez utiliser l'objet global pour faire la même chose.


Je vais aller avec cette solution pour l'instant, totaly a oublié que tout est une fonction, donc aussi la fenêtre globale objet / fonctions / espaces de noms :)


@Dribbel - ça sonne bien. Je n'ai utilisé que la fenêtre parce que je n'étais pas certain de l'espace de noms. Je vous recommanderais de les définir dans un autre espace de noms si vous utilisez fenêtre . La même technique peut être utilisée, mais si getTool ne fait rien d'autre, vous pouvez éliminer cet appel de fonction.



8
votes

Vous devriez envisager de repenser votre approche. Il serait préférable d'avoir quelque chose comme un objet outil , qui aurait les outils comme propriétés, comme xxx

de cette façon, vous pouvez accéder aux outils à la fois < Code> Nouveaux outils.SelectTool et nouveaux outils [var_with_tool_name] .


1 commentaires

Oui, mais cela fonctionne même si les outils sont dans différents espaces de noms.



3
votes

Dans votre exemple, vous déclarez PointeroTool code> en fonction de la portée globale. En supposant que votre JavaScript exécute le navigateur, la "portée globale" est réellement em> identique à la fenêtre fenêtre code>. Cela signifie que si vous avez un constructeur: xxx pré>

c'est identique à celui-ci: p> xxx pré>

donc maintenant, dans votre fonction getTool, vous Peut accéder à vos fonctions de constructeur comme ceci: p> xxx pré>


une façon plus "future preuve" de faire cela serait de définir votre propre objet d'espace de noms, dans lequel vous " ll placer tous vos différents constructeurs d'outils. Quelque chose comme ça ("myProject" serait le nom abrégé de votre projet ou de votre système): p> xxx pré>

alors votre fonction getTool ressemblerait à ceci: p>

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


2 commentaires

Non, Fonction PointeroTool fenêtre.pointool = fonction : la première est une fonction déclaration , la seconde une fonction expression . kangax.github.com/nfe/#expr-vs-decl


Vrai, mais dans le contexte de cette question, il est assez égal. C'est-à-dire que vous pouvez référencer pointerotan à l'aide de window.pointooltool , qui est le point de cette réponse.