Existe-t-il des moyens «harmonieux» pour obtenir le nom de classe à partir de l'instance de classe ES6? Autre que
someClassInstance.constructor.name
Actuellement je compte sur l'implémentation de Traceur. Et il semble que Babel ait un polyfill pendant Function.name
que Traceur n'en a pas.
Pour résumer le tout: il n'y avait pas d'autre moyen dans ES6 / ES2015 / Harmony, et rien n'est attendu ATM dans ES.Next.
Il peut fournir des modèles utiles pour les applications côté serveur non réduites mais n'est pas souhaité dans les applications destinées au navigateur / bureau / mobile.
Babel utilisecore-js
pour polyfill Function.name
, il doit être chargé manuellement pour les applications Traceur et TypeScript selon le cas.
javascript
ecmascript-6
traceur
Fiole d'Estus
la source
la source
instance.constructor.name
etclass.name
renvoyez le nom de la classe dans ES6 approprié.someClassInstance.constructor.name
sera mutilé si vous uglifiez votre code..constructor
.Réponses:
someClassInstance.constructor.name
est exactement la bonne façon de procéder. Les transpileurs peuvent ne pas prendre en charge cela, mais c'est la méthode standard selon la spécification. (Laname
propriété des fonctions déclarées via les productions ClassDeclaration est définie dans 14.5.15 , étape 6.)la source
someClassInstance.constructor
est une fonction. Toutes les fonctions ont unename
propriété définie sur son nom. C'est pourquoi Babel n'a rien à faire. Veuillez consulter developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Comme le dit @Domenic, utilisez
someClassInstance.constructor.name
. @Esteban mentionne dans les commentaires queAinsi, pour accéder au nom de la classe de façon statique, procédez comme suit (cela fonctionne avec ma version Babel BTW. Selon les commentaires sur @Domenic votre kilométrage peut varier).
Mettre à jour
Babel allait bien, mais uglify / minification a fini par me causer des problèmes. Je crée un jeu et je crée un hachage de ressources Sprite mises en commun (où la clé est le nom de la fonction). Après la minification, chaque fonction / classe a été nommée
t
. Cela tue le hachage. J'utiliseGulp
dans ce projet, et après avoir lu la documentation gulp-uglify, j'ai découvert qu'il y avait un paramètre pour empêcher cette modification du nom de la variable / fonction locale. Donc, dans mon gulpfile j'ai changé.pipe($.uglify())
à.pipe($.uglify({ mangle: false }))
Il y a ici un compromis entre performances et lisibilité. Ne pas modifier les noms entraînera un fichier de construction (légèrement) plus volumineux (plus de ressources réseau) et une exécution de code potentiellement plus lente (citation nécessaire - peut être BS). D'un autre côté, si je gardais la même chose, je devrais définir manuellement
getClassName
sur chaque classe ES6 - au niveau statique et de l'instance. Non merci!Mettre à jour
Après la discussion dans les commentaires, il semble qu'éviter la
.name
convention en faveur de la définition de ces fonctions soit un bon paradigme. Cela ne prend que quelques lignes de code et permettra une minification complète et une généralisation de votre code (s'il est utilisé dans une bibliothèque). Donc je suppose que je change d'avis et que je définirai manuellementgetClassName
mes cours. Merci @estus! . Les Getter / Setters sont généralement une bonne idée par rapport à l'accès direct aux variables de toute façon, en particulier dans une application client.la source
reserved
option Uglify (une liste de classes peut être obtenue avec regexp ou autre).name
modèle soigné peut simplement être gagnant-gagnant. La même chose peut être appliquée à Node, mais dans une moindre mesure (par exemple, application Electron masquée). En règle générale, je me fieraisname
au code serveur, mais pas au code navigateur ni à la bibliothèque commune.name
code DRYer pour extraire le nom de l'entité qui utilise la classe (service, plugin, etc.) du nom de la classe, mais à la fin, j'ai trouvé qu'il le dupliquait explicitement avec static prop (id
,_name
) est juste l'approche la plus solide. Une bonne alternative est de ne pas se soucier du nom de la classe, d'utiliser une classe elle-même (objet fonction) comme identifiant pour une entité mappée à cette classe etimport
là où c'est nécessaire (une approche qui a été utilisée par Angular 2 DI).Obtenir le nom de la classe directement depuis la classe
Les réponses précédentes ont expliqué que cela
someClassInstance.constructor.name
fonctionne très bien, mais si vous devez convertir par programme le nom de la classe en une chaîne et que vous ne voulez pas créer une instance juste pour cela, rappelez-vous que:Et, puisque chaque fonction a une
name
propriété, une autre manière intéressante d'obtenir une chaîne avec le nom de votre classe est de simplement faire:Ce qui suit est un bon exemple de pourquoi cela est utile.
Chargement des composants Web
Comme nous l'enseigne la documentation MDN, voici comment charger un composant Web:
D'où
YourComponent
vient une classe qui s'étendHTMLElement
. Puisqu'il est considéré comme une bonne pratique de nommer la classe de votre composant après la balise de composant elle-même, il serait bien d'écrire une fonction d'assistance que tous vos composants pourraient utiliser pour s'enregistrer. Voici donc cette fonction:Il vous suffit donc de:
Ce qui est bien car c'est moins sujet aux erreurs que d'écrire vous-même la balise de composant. Pour conclure, voici la
upperCamelCaseToSnakeCase()
fonction:la source
Pour la transpilation babel (avant minification)
Si vous utilisez Babel avec
@babel/preset-env
, il est possible de conserver les définitions de classes sans les convertir en fonctions (ce qui supprime laconstructor
propriété)Vous pouvez supprimer une ancienne compatibilité de navigateur avec cette configuration dans votre
babel.config / babelrc
:Pour la minification de babel (après transpilation)
Il semble qu'il n'y a pas de solution facile pour le moment ... Nous devons envisager de réduire les exclusions.
la source
class Foo {}
sera réduit à quelque chose commeclass a{}
avec n'importe quelle cible. Il n'y aura aucunFoo
mot dans le code source minifié.export class Foo{}
ils ne peuvent pas être davantage modifiés de manière efficace, mais cela peut être différent à d'autres endroits, nous ne pouvons pas savoir exactement comment sans avoir une bonne idée de ce qui se passe avec des morceaux de code spécifiques au moment de la construction. Quoi qu'il en soit, cela n'a pas changé depuis 2015. C'était toujours possible pour certaines configurations de compilation et du code. Et je dirais que cette possibilité est encore trop fragile pour utiliser des noms de classe pour la logique d'application. Le nom de classe sur lequel vous comptez peut devenir une poubelle après un changement accidentel du code sourceconstructor.name
fonctionne toujours dans la version minifiée ... illogique: /