ES6クラスインスタンスからクラス名を取得するための「調和のとれた」方法はありますか?以外
someClassInstance.constructor.name
現在私はTraceurの実装を頼りにしています。そして、BaburはFunction.name
のためのpolyfillを持っていますが、Traceurは持っていません。
まとめると、ES6/ES2015/Harmonyには他に方法はありませんでした。ES.NextではATMは想定されていません。
これは、縮小されていないサーバーサイドアプリケーションに有用なパターンを提供するかもしれませんが、ブラウザ/デスクトップ/モバイル向けのアプリケーションでは望ましくありません。
Babel core-js
をpolyfillに使用する Function.name
、TraceurとTypeScriptアプリケーションには適宜手動でロードしてください。
someClassInstance.constructor.name
はまさにこれを行う正しい方法です。 Transpilerはこれをサポートしないかもしれませんが、それは仕様に従って標準的な方法です。 (ClassDeclarationプロダクションを介して宣言された関数のname
プロパティは 14.5.15 、ステップ6に設定されています。)
@Domenicが言うように、someClassInstance.constructor.name
を使用してください。 @Estebanは、コメントで言及していること
someClassInstance.constructor
は関数です。すべての関数はname
プロパティを持っています...
したがって、静的にクラス名にアクセスするには、次のようにします(これは私のBabelバージョンBTWで動作します。@Domenicのコメントによると、あなたの走行距離は変わるかもしれません)。
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
更新
Babelは大丈夫だったが、醜化/縮小は結局私に問題を引き起こした。私はゲームを作っていて、プールされたSpriteリソースのハッシュを作成しています(キーは関数名です)。縮小後、すべての関数/クラスはt
と命名されました。これはハッシュを殺します。私はこのプロジェクトでGulp
を使用しています、そして gulp-uglify docs を読んだ後、このローカル変数/関数名のマングリングを防ぐためのパラメータがあることを発見しました。だから、私のgulpファイルで私は変更しました
.pipe($.uglify())
から.pipe($.uglify({ mangle: false }))
ここではパフォーマンスと読みやすさの間にトレードオフがあります。名前を乱さないと(少し)大きなビルドファイル(より多くのネットワークリソース)と潜在的により遅いコード実行(引用が必要です - BSかもしれません)をもたらすでしょう。一方、同じままにしておくと、すべてのES6クラスで静的およびインスタンスレベルでgetClassName
を手動で定義する必要があります。結構です!
更新
コメントでの議論の後、それらの関数を定義するために.name
規約を避けることは良いパラダイムのようです。数行のコードしか必要とせず、あなたのコードの完全な縮小と一般化を可能にします(ライブラリで使用されている場合)。ですから、考えを変えて、クラスにgetClassName
を手動で定義するつもりです。ありがとう @ estus! 。とくにクライアントベースのアプリケーションでは、直接変数アクセスと比較して、ゲッター/セッターは通常は良い考えです。
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)
前の回答ではsomeClassInstance.constructor.name
は問題なく動作すると説明しましたが、プログラムでクラス名を文字列に変換する必要があり、そのためだけにインスタンスを作成したくない場合は、次の点に注意してください。
typeof YourClass === "function"
そして、すべての関数がname
プロパティを持っているので、あなたのクラス名で文字列を取得するもう一つの良い方法はただすることです:
YourClass.name
以下は、これが便利な理由の良い例です。
MDNドキュメント が教えてくれるように、これがWebコンポーネントのロード方法です。
customElements.define("your-component", YourComponent);
YourComponent
はHTMLElement
から拡張するクラスです。コンポーネントのタグ自体の名前に基づいてコンポーネントのクラスに名前を付けるのは良い習慣と考えられているので、すべてのコンポーネントが自分自身を登録するために使用できるヘルパー関数を書くのはいいでしょう。これがその機能です。
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
だからあなたがする必要があるのは次のとおりです。
registerComponent(YourComponent);
コンポーネントタグを自分で記述するよりもエラーが発生しにくいので、これはいい方法です。まとめると、これはupperCamelCaseToSnakeCase()
関数です。
// 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());
}