Czy są jakieś „harmonijne” sposoby uzyskania nazwy klasy z instancji klasy ES6? Inny niż
someClassInstance.constructor.name
Obecnie liczę na wdrożenie Traceur. I wydaje się, że Babel ma polyfill, Function.name
podczas gdy Traceur nie.
Podsumowując: w ES6 / ES2015 / Harmony nie było innej drogi, aw ES nie oczekuje się ATM. Dalej.
Może dostarczać użytecznych wzorców dla niezminimalizowanych aplikacji po stronie serwera, ale jest niepożądany w aplikacjach przeznaczonych dla przeglądarek / komputerów stacjonarnych / urządzeń przenośnych.
Babel używacore-js
do wypełniania Function.name
, powinien być ładowany ręcznie dla aplikacji Traceur i TypeScript, jeśli jest to właściwe.
javascript
ecmascript-6
traceur
Estus Flask
źródło
źródło
instance.constructor.name
iclass.name
zwróci nazwę klasy w odpowiednim ES6.someClassInstance.constructor.name
zostanie zniekształcony, jeśli zmienisz kod..constructor
.Odpowiedzi:
someClassInstance.constructor.name
jest dokładnie właściwym sposobem, aby to zrobić. Transpilery mogą tego nie obsługiwać, ale jest to standardowy sposób w specyfikacji. (name
Właściwość funkcji zadeklarowanych przez produkcje ClassDeclaration jest ustawiana w 14.5.15 , krok 6.)źródło
someClassInstance.constructor
to funkcja. Wszystkie funkcje mająname
właściwość, która jest ustawiona na nazwę. Dlatego babel nie musi nic robić. Zobacz developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Jak mówi @Domenic, użyj
someClassInstance.constructor.name
. @Esteban wspomina w komentarzach, żeTak więc, aby uzyskać statyczny dostęp do nazwy klasy, wykonaj następujące czynności (przy okazji działa to z moją wersją Babel. Zgodnie z komentarzami na @Domenic Twój przebieg może się różnić).
Aktualizacja
Babel był w porządku, ale uglifikacja / minifikacja ostatecznie spowodowała problemy. Tworzę grę i tworzę skrót zasobów Sprite w puli (gdzie kluczem jest nazwa funkcji). Po minifikacji każda funkcja / klasa została nazwana
t
. To zabija haszysz. UżywamGulp
w tym projekcie i po przeczytaniu dokumentacji gulp-uglify odkryłem, że istnieje parametr zapobiegający zmianie lokalnej nazwy zmiennej / funkcji. Więc zmieniłem się w moim pliku łykowym.pipe($.uglify())
do.pipe($.uglify({ mangle: false }))
Występuje tutaj kompromis między wydajnością a czytelnością. Brak zniekształcenia nazw spowoduje (nieco) większy plik kompilacji (więcej zasobów sieciowych) i potencjalnie wolniejsze wykonanie kodu (potrzebne źródło - może to być BS). Z drugiej strony, gdybym zachował to samo, musiałbym ręcznie zdefiniować
getClassName
dla każdej klasy ES6 - na poziomie statycznym i instancji. Nie, dziękuję!Aktualizacja
Po dyskusji w komentarzach wydaje się, że unikanie
.name
konwencji na rzecz definiowania tych funkcji to dobry paradygmat. Zajmuje tylko kilka wierszy kodu i pozwoli na pełną minifikację i ogólność kodu (jeśli jest używany w bibliotece). Więc chyba zmienię zdanie i ręcznie zdefiniujęgetClassName
na moich zajęciach. Dzięki @estus! . Getter / Setters i tak są zwykle dobrym pomysłem w porównaniu do bezpośredniego dostępu do zmiennych, zwłaszcza w aplikacji opartej na kliencie.źródło
reserved
zniekształceniem za pomocą opcji Uglify (listę klas można uzyskać za pomocą regexp lub cokolwiek innego).name
wzorca może być po prostu korzystna dla obu stron. To samo można zastosować do Node, ale w mniejszym stopniu (np. Zaciemniona aplikacja Electron). Z reguły oparłbym się naname
kodzie serwera, ale nie na kodzie przeglądarki i nie na wspólnej bibliotece.name
użyłem kodu DRYer do wyodrębnienia nazwy jednostki używającej klasy (usługi, wtyczki itp.) Z nazwy klasy, ale w końcu odkryłem, że kopiuje ją jawnie za pomocą statycznej właściwości (id
,_name
) jest po prostu najbardziej solidnym podejściem. Dobrą alternatywą jest nie przejmowanie się nazwą klasy, używanie samej klasy (obiektu funkcji) jako identyfikatora dla jednostki, która jest mapowana na tę klasę iimport
wszędzie tam, gdzie jest to potrzebne (podejście, które było używane przez Angular 2 DI).Pobieranie nazwy klasy bezpośrednio z klasy
Poprzednie odpowiedzi wyjaśniły, że to
someClassInstance.constructor.name
działa dobrze, ale jeśli chcesz programowo przekonwertować nazwę klasy na ciąg i nie chcesz tworzyć instancji tylko do tego, pamiętaj, że:A ponieważ każda funkcja ma
name
właściwość, innym dobrym sposobem na uzyskanie ciągu znaków z nazwą klasy jest wykonanie:Poniżej znajduje się dobry przykład tego, dlaczego jest to przydatne.
Ładowanie komponentów internetowych
Jak uczy dokumentacja MDN , ładowanie komponentu internetowego jest następujące:
Skąd
YourComponent
pochodzi klasaHTMLElement
. Ponieważ nazywanie klasy komponentu po samym tagu komponentu jest uważane za dobrą praktykę, dobrze byłoby napisać funkcję pomocniczą, której wszystkie komponenty mogłyby się zarejestrować. Oto ta funkcja:Więc wszystko, co musisz zrobić, to:
Co jest miłe, ponieważ jest mniej podatne na błędy niż samodzielne pisanie tagu komponentu. Podsumowując, oto
upperCamelCaseToSnakeCase()
funkcja:źródło
Do transpilacji babel (przed minifikacją)
Jeśli używasz Babel z
@babel/preset-env
, możliwe jest zachowanie definicji klas bez konwertowania ich na funkcje (co usuwaconstructor
właściwość)Możesz zrezygnować ze starej zgodności przeglądarki z tą konfiguracją w
babel.config / babelrc
:Do minifikacji babel (po transpilacji)
Wygląda na to, że w tej chwili nie ma łatwego rozwiązania ... Musimy przyjrzeć się zniekształconym wykluczeniom.
źródło
class Foo {}
zostanie zminimalizowany do czegoś podobnegoclass a{}
do dowolnego celu. WFoo
zminimalizowanym kodzie źródłowym nie będzie słowa.export class Foo{}
nie mogą być dalej skutecznie zniekształcone, ale w innych miejscach może być inaczej, nie możemy wiedzieć, jak dokładnie, nie mając dobrego pojęcia, co dzieje się z określonymi fragmentami kodu w czasie kompilacji. W każdym razie nie zmieniło się to od 2015 roku. Zawsze było to możliwe dla niektórych konfiguracji i kodu kompilacji. I powiedziałbym, że ta możliwość jest nadal zbyt delikatna, aby używać nazw klas w logice aplikacji. Nazwa klasy, na której polegasz, może stać się śmieciami po jednej przypadkowej zmianie w kodzie źródłowymconstructor.name
nadal działa w zminimalizowanej wersji ... nielogiczne: /