【JavaScript】変数がclassかどうかを判定する方法
更新日:2024/02/27
JavaScriptで変数がクラス定義かどうかと、クラスのインスタンスかどうかを判定する方法を紹介します。
変数がclass定義かどうかを判定
まずは、変数がclass定義かどうかを判定するケースです。
コード
変数がclass定義かどうかは、次のコードで判定できます。
const isClassDefine = value =>typeof value === "function"
&& Boolean(value.toString?.().match( /^class[ {\n\r]/ ));
幾つかの値で、判定してみます。
const clss = class{};
const clss2 = class extends clss{};
console.log( isClassDefine(clss) ); // 結果: true
console.log( isClassDefine(clss2) ); // 結果: true
console.log( isClassDefine(new clss) ); // 結果: false
console.log( isClassDefine(new clss2) ); // 結果: false
console.log( isClassDefine(function(){}) ); // 結果: false
console.log( isClassDefine(class1=>{}) ); // 結果: false
console.log( isClassDefine({a:1,b:2}) ); // 結果: false
解説
JavaScriptはclassオブジェクトのようなクラス特有のオブジェクトがありません。
class構文は、functionオブジェクトに変換されます。
そのため、まず変数がfunctionオブジェクトかどうかを確認しています。
また、functionオブジェクトのtoString()を実行すると、ソースコードが表示されます。
そのため、classで始まるかどうかを確認することで、class構文かどうかを判定できます。
ただしアロー関数で、class1=>{}のようなコードが成立します。
このことを考慮して正規表現でマッチさせています。
変数がclass定義のインスタンスかどうかを判定
次は、変数がclass定義から派生したインスタンスかどうかを判定します。
コード
class定義のインスタンスかどうかは、次のコードで判定できます。
const isClassInstance = value =>typeof value === "object"
&& Boolean(
Object.getPrototypeOf(value).constructor?.toString?.()
.match( /^class[ {\n\r]/ )
);
幾つかの値で、判定してみます。
const clss = class{};
const clss2 = class extends clss{};
console.log( isClassDefine(clss) ); // 結果: false
console.log( isClassDefine(clss2) ); // 結果: false
console.log( isClassDefine(new clss) ); // 結果: true
console.log( isClassDefine(new clss2) ); // 結果: true
console.log( isClassDefine(function(){}) ); // 結果: false
console.log( isClassDefine(class1=>{}) ); // 結果: false
console.log( isClassDefine({a:1,b:2}) ); // 結果: false
解説
classのインスタンスはobject型になります。
そこで、最初にobject型かどうかを確認しています。
オブジェクトは最初のプロトタイプチェーンのconstructorプロパティに、元となったコンストラクターへの参照がセットされています。
※class定義もコンストラクターです。
このコンストラクターにtoString()を実行するとソースコードを取得できます。
後は、前項と同様にclassで始まるかをチェックします。
変数が特定のクラスのインスタンスかどうかを判定する
変数が特定のクラスのインスタンスかどうかを判定するときは、instanceofを使用します。
const clss = class {};
console.log( new clss instanceof clss ); // 結果: true
ただしinstanceofは、派生を遡ります。
const clss2 = class extends clss{};
const s2 = new clss2;
console.log( s2 instanceof clss2 ); // 結果: true
console.log( s2 instanceof clss ); // 結果: true
console.log( s2 instanceof Object ); // 結果: true
生成元のクラスを特定したいときは、次のようにインスタンスのプロトタイプと、クラス定義のprototypeプロパティを比較します
console.log( Object.getPrototypeOf(s2) === clss2.prototype ); // 結果: true
console.log( Object.getPrototypeOf(s2) === clss.prototype ); // 結果: false
console.log( Object.getPrototypeOf(s2) === Object.prototype ); // 結果: false
一致すれば、生成元のクラスということになります。
更新日:2024/02/27
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。