javascript - ES6 sınıf örneğinin sınıf adını almak
ES6 sınıf örneğinden sınıf adını almak için başka 'uyumlu' yollar var mı?
someClassInstance.constructor.name
Şu anda Traceur uygulamasına güveniyorum. Görünüşe göre Babel'in Function.name için bir polyfill'i var, oysa Traceur'un yok.
Özetle: ES6/ES2015/Harmony'de başka bir yol yoktu ve ES.Next'te şu anda hiçbir şey beklenmiyor.
Bu, minify edilmemiş sunucu tarafı uygulamaları için faydalı desenler sağlayabilir, ancak tarayıcı/masaüstü/mobil için tasarlanmış uygulamalarda istenmez.
Babel, Function.name'i polifill yapmak için core-js kullanır, Traceur ve TypeScript uygulamaları için uygun şekilde manuel olarak yüklenmelidir.
Cevap #1
someClassInstance.constructor.name bunu yapmanın tam olarak doğru yoludur. Transpilerlar bunu desteklemeyebilir, ancak bu, spesifikasyona göre standart yoldur. (ClassDeclaration üretimleri ile tanımlanan fonksiyonların name özelliği 14.5.15, adım 6'da ayarlanır.)
Cevap #2
Domenic'in dediği gibi, someClassInstance.constructor.name kullanın. Esteban yorumlarda bahsediyor ki
someClassInstance.constructorbir Fonksiyondur. Tüm Fonksiyonların birnameözelliği vardır...
Dolayısıyla, sınıf adına statik olarak erişmek için aşağıdakileri yapın (bu arada, bu benim Babel sürümümde çalışıyor. @Domenic üzerindeki yorumlara göre, sizin deneyiminiz farklı olabilir).
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
Güncelleme
Babel iyiydi, ama uglify/minifikasyon bana sorunlar çıkardı. Bir oyun yapıyorum ve bir havuzlanmış Sprite kaynaklarının (anahtarın fonksiyon adı olduğu yerde) hash'ini oluşturuyorum. Minifikasyondan sonra, her fonksiyon/sınıf t olarak adlandırıldı. Bu hash'i öldürüyor. Bu projede Gulp kullanıyorum ve gulp-uglify belgelerini okuduktan sonra, bu yerel değişken/fonksiyon adı karıştırma işleminin gerçekleşmesini önleyecek bir parametre olduğunu keşfettim. Bu yüzden, gulpfile'ımda şunu değiştirdim
.pipe($.uglify()) öğesini .pipe($.uglify({ mangle: false })) öğesine çevir
Burada performans ile okunabilirlik arasında bir takas var. İsimleri bozmamak, (biraz) daha büyük bir derleme dosyası (daha fazla ağ kaynağı) ve potansiyel olarak daha yavaş kod yürütmesi ile sonuçlanacaktır (alıntı gerekli - belki de yanlış olabilir). Öte yandan, aynı şekilde bıraksaydım, her ES6 sınıfında getClassName'i hem statik hem de örnek düzeyinde manuel olarak tanımlamak zorunda olurdum. Hayır, teşekkürler!
Güncelleme
Yorumlardaki tartışmanın ardından, bu işlevleri tanımlamayı tercih ederek .name kullanımından kaçınmanın iyi bir paradigma gibi göründüğünü düşünüyorum. Sadece birkaç satır kod alıyor ve kodunuzun (bir kütüphanede kullanılıyorsa) tam minifikasyonuna ve genelliğine izin veriyor. Yani sanırım fikrimi değiştiriyorum ve sınıflarımda getClassName metodunu manuel olarak tanımlayacağım. Teşekkürler @estus! Getter/Setter kullanmak genellikle doğrudan değişken erişimine göre iyi bir fikir, özellikle de istemci tabanlı bir uygulamada.
class SomeClass {
constructor() {}
static getClassName(){ return 'SomeClass'; }
getClassName(){ return SomeClass.getClassName(); }
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.getClassName(); // === 'SomeClass' (static fn)
someClassInstance.getClassName(); // === 'SomeClass' (instance fn)
SomeClass.getClassName() // === 'SomeClass' (static fn)
Cevap #3
Sınıftan doğrudan sınıf adını alma
Önceki cevaplar, someClassInstance.constructor.name ifadesinin tamamen çalıştığını açıkladı, ancak sınıf adını programlı olarak bir stringe dönüştürmeniz gerekiyor ve sadece bunun için bir örnek yaratmak istemiyorsanız, şunu unutmayın:
typeof YourClass === "function"
Ve, her fonksiyonun bir name özelliği olduğundan, sınıf adınızı bir string olarak almanın başka güzel bir yolu da sadece şunu yapmaktır:
YourClass.name
Aşağıda bunun neden faydalı olduğuna dair iyi bir örnek bulunmaktadır.
Web bileşenleri yükleniyor
MDN dokümantasyonunun bize öğrettiği gibi, bir web bileşenini şöyle yüklersiniz:
customElements.define("your-component", YourComponent);
YourComponent, HTMLElement'den türeyen bir sınıftır. Bileşen sınıfınızı bileşen etiketiyle aynı adla adlandırmak iyi bir uygulama olarak kabul edildiğinden, tüm bileşenlerinizin kendilerini kaydetmek için kullanabileceği bir yardımcı fonksiyon yazmak güzel olur. İşte o fonksiyon:
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
Yapmanız gereken tek şey şudur:
registerComponent(YourComponent);
Bu hoş çünkü bileşen etiketini kendiniz yazmaktan daha az hata yapma eğilimlidir. Özetlemek gerekirse, işte upperCamelCaseToSnakeCase() fonksiyonu:
// converts `YourString` into `your-string`
function upperCamelCaseToSnakeCase(value) {
return value
// first char to lower case
.replace(/^([A-Z])/, $1 => $1.toLowerCase())
// following upper chars get preceded with a dash
.replace(/([A-Z])/g, $1 => "-" + $1.toLowerCase());
}
