Gibt es harmonische Möglichkeiten, den Klassennamen von der ES6-Klasseninstanz abzurufen? Außer
someClassInstance.constructor.name
Derzeit zähle ich auf die Implementierung von Traceur. Und es scheint, dass Babel eine Polyfüllung hat, Function.name
Traceur nicht.
Um es zusammenzufassen: In ES6 / ES2015 / Harmony gab es keinen anderen Weg, und in ES.Next wird kein Geldautomat erwartet.
Es kann nützliche Muster für nicht minimierte serverseitige Anwendungen bereitstellen, ist jedoch in Anwendungen für Browser / Desktop / Mobile unerwünscht.
Babel verwendetcore-js
zum Polyfill Function.name
, es sollte für Traceur- und TypeScript-Anwendungen entsprechend manuell geladen werden.
javascript
ecmascript-6
traceur
Estus Flask
quelle
quelle
instance.constructor.name
undclass.name
geben Sie den Klassennamen in ES6 zurück.someClassInstance.constructor.name
entstellt wird, wenn Sie Ihren Code hässlich machen..constructor
.Antworten:
someClassInstance.constructor.name
ist genau der richtige Weg, dies zu tun. Transpiler unterstützen dies möglicherweise nicht, aber es ist der Standardweg gemäß der Spezifikation. (Diename
Eigenschaft von Funktionen, die über ClassDeclaration-Produktionen deklariert wurden , wird in 14.5.15 , Schritt 6 festgelegt.)quelle
someClassInstance.constructor
ist eine Funktion. Alle Funktionen haben einename
Eigenschaft, die auf ihren Namen festgelegt ist. Deshalb muss babel nichts tun. Bitte sehen Sie developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Wie @Domenic sagt, verwenden Sie
someClassInstance.constructor.name
. @Esteban erwähnt in den Kommentaren, dassUm statisch auf den Klassennamen zuzugreifen, gehen Sie wie folgt vor (dies funktioniert übrigens mit meiner Babel-Version. Gemäß den Kommentaren zu @Domenic kann Ihr Kilometerstand variieren).
Aktualisieren
Babel ging es gut, aber Uglify / Minification verursachte mir Probleme. Ich mache ein Spiel und erstelle einen Hash gepoolter Sprite-Ressourcen (wobei der Schlüssel der Funktionsname ist). Nach der Minimierung wurde jede Funktion / Klasse benannt
t
. Dies tötet den Hash. Ich verwende esGulp
in diesem Projekt und nachdem ich die gulp-uglify-Dokumente gelesen habe, habe ich festgestellt, dass es einen Parameter gibt, der verhindert, dass diese lokale Variable / Funktionsname beschädigt wird. Also habe ich mich in meinem Gulpfile verändert.pipe($.uglify())
zu.pipe($.uglify({ mangle: false }))
Hier gibt es einen Kompromiss zwischen Leistung und Lesbarkeit. Wenn die Namen nicht entstellt werden, führt dies zu einer (geringfügig) größeren Build-Datei (mehr Netzwerkressourcen) und möglicherweise zu einer langsameren Codeausführung (Zitieren erforderlich - möglicherweise BS). Wenn ich es jedoch gleich halten würde, müsste ich es
getClassName
für jede ES6-Klasse manuell definieren - auf statischer und Instanzebene. Nein Danke!Aktualisieren
Nach der Diskussion in den Kommentaren scheint
.name
es ein gutes Paradigma zu sein , die Konvention zugunsten der Definition dieser Funktionen zu vermeiden . Es dauert nur wenige Codezeilen und ermöglicht eine vollständige Minimierung und Allgemeingültigkeit Ihres Codes (falls in einer Bibliothek verwendet). Ich denke, ich ändere meine Meinung und werdegetClassName
meine Klassen manuell definieren . Danke @estus! . Getter / Setter sind normalerweise eine gute Idee im Vergleich zum direkten Variablenzugriff, insbesondere in einer Client-basierten Anwendung.quelle
reserved
Option Uglify vor Verfälschungen geschützt werden (eine Liste der Klassen kann mit regulärem Ausdruck oder was auch immer abgerufen werden).name
Musters kann nur eine Win-Win-Situation sein. Das Gleiche kann auf Node angewendet werden, jedoch in geringerem Maße (z. B. verschleierte Elektronen-App). Als Faustregel würde ich mich auf denname
Servercode verlassen, aber nicht auf den Browsercode und nicht auf die gemeinsame Bibliothek.name
DRYer-Code verwendet, um den Namen der Entität, die die Klasse (Dienst, Plugin usw.) verwendet, aus dem Klassennamen zu extrahieren, aber am Ende habe ich festgestellt, dass sie explizit mit static prop (id
,_name
) dupliziert wird. ist nur der solideste Ansatz. Eine gute Alternative besteht darin, sich nicht um den Klassennamen zu kümmern, eine Klasse selbst (Funktionsobjekt) als Bezeichner für eine Entität zu verwenden, die dieser Klasse zugeordnet ist, undimport
sie, wo immer dies erforderlich ist (ein Ansatz, der von Angular 2 DI verwendet wurde).Abrufen des Klassennamens direkt von der Klasse
In früheren Antworten wurde erklärt, dass dies einwandfrei
someClassInstance.constructor.name
funktioniert. Wenn Sie jedoch den Klassennamen programmgesteuert in eine Zeichenfolge konvertieren müssen und keine Instanz dafür erstellen möchten, denken Sie daran:Und da jede Funktion eine
name
Eigenschaft hat, können Sie auch eine Zeichenfolge mit Ihrem Klassennamen abrufen:Was folgt, ist ein gutes Beispiel dafür, warum dies nützlich ist.
Laden von Webkomponenten
Wie aus der MDN-Dokumentation hervorgeht , laden Sie eine Webkomponente folgendermaßen:
Wo
YourComponent
ist , die sich eine Klasse ausHTMLElement
. Da es als bewährte Methode angesehen wird, die Klasse Ihrer Komponente nach dem Komponenten-Tag selbst zu benennen, wäre es hilfreich, eine Hilfsfunktion zu schreiben, mit der sich alle Ihre Komponenten registrieren könnten. Hier ist also diese Funktion:Alles was Sie tun müssen ist:
Das ist schön, weil es weniger fehleranfällig ist, als das Komponenten-Tag selbst zu schreiben. Zum Abschluss ist dies die
upperCamelCaseToSnakeCase()
Funktion:quelle
Zur Babeltranspilation (vor der Minifizierung)
Wenn Sie Babel mit verwenden
@babel/preset-env
, ist es möglich, Klassendefinitionen beizubehalten, ohne sie in Funktionen zu konvertieren (wodurch das entfernt wirdconstructor
Eigenschaft entfernt wird).Sie können einige alte Browserkompatibilitäten mit dieser Konfiguration in Ihrem Verzeichnis löschen
babel.config / babelrc
:Zur Babelminimierung (nach Transpilation)
Es sieht so aus, als ob es momentan keine einfache Lösung gibt ... Wir müssen uns die Ausschlüsse von Verstümmelungen ansehen.
quelle
class Foo {}
wird auf so etwas wieclass a{}
mit jedem Ziel minimiert . DerFoo
minimierte Quellcode enthält kein Wort.export class Foo{}
beibehalten werden, da sie nicht weiter effizient hässlich gemacht werden können. Dies kann jedoch an anderen Stellen anders sein. Wir können nicht genau wissen, wie, ohne eine gute Vorstellung davon zu haben, was mit bestimmten Codeteilen zur Erstellungszeit geschieht. Auf jeden Fall hat sich dies seit 2015 nicht geändert. Für einige Kompilierungskonfigurationen und Code war dies immer möglich. Und ich würde sagen, diese Möglichkeit ist immer noch zu fragil, um Klassennamen für die App-Logik zu verwenden. Der Klassenname, auf den Sie sich verlassen, kann nach einer versehentlichen Änderung des Quellcodes zu Müll werdenconstructor.name
gesamter Code in der minimierten Version noch funktioniert ... unlogisch: /