2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JavaScriptでクラスなのかを判定してメンバを列挙する

Last updated at Posted at 2022-11-20

概要

Javascriptでクラスを判定してメンバを列挙する必要が出てきたのでやり方を探してみた。
Node.js・Chromeで確認
JavaScriptのクラス関係の命名がよくわからなかったのでJava基準で

クラスの判別

クラス・インスタンスを普通にtypeofに通すとクラスはfunction、インスタンスはobjectと返ります。JavaScriptのクラスが単なる糖衣構文に過ぎないことがよくわかります。

class TestClass {
    static classMethodTest(){}
    static classFieldTest;
    static arguments;
    instanceMethodTest(){}
    instanceFieldTest;
}

let TestObject = {
    constructor: ''
}

let TestFunction = function() {
}

let TestInstance = new TestClass();

console.log(typeof TestClass);       // "function"

console.log(typeof TestInstance);    // "object"

クラスであることを判定するにはtoString()でコードを取得して先頭がclassであるかどうかを確認するのが確実なんじゃないかと思います。
一応クラスにはfunctionオブジェクトにあるはずのargumentプロパティがないのですが、自分でargumentクラスフィールドを追加したら判別のしようがなくなるので・・・

console.log(TestClass.toString().startsWith('class'));   //true

インスタンスの場合はconstructorプロパティでクラスを取得できるはずなのでそこからtoString()でクラスかどうかを判別します。

console.log(TestInstance.constructor.toString().startsWith('class'));    //true

基底クラスの取得

Object.getPrototypeOf(TestClass);とすると基底クラスを取得できます。

ルートクラスにあたるObjectクラス?に行き当たるとtoStringの結果がfunction () { [native code] }になるので基底クラスを辿っていくのは簡単です。

thisobj = TestClass;
while (true) {
    classname = thisobj.name;
    console.log(classname);
    thisobj = Object.getPrototypeOf(thisobj);
    if (!thisobj.toString().startsWith('class')) break;
}

メンバの列挙

クラスに定義したメンバはなぜかObject.keys()では取得できません、代わりにObject.getOwnPropertyNames()を使います。

JavaScriptには列挙可能なプロパティと列挙不可能なプロパティってのがあるらしくObject.Keys()で取得できるのは前者だけだかららしい。

//(1) ['constructor']
console.log(Object.getOwnPropertyNames(TestObject));

//(5) ['length', 'name', 'arguments', 'caller', 'prototype']
console.log(Object.getOwnPropertyNames(TestFunction));

//(6) ['length', 'name', 'prototype', 'classMethodTest', 'classFieldTest', 'arguments']
console.log(Object.getOwnPropertyNames(TestClass));

//(2) ['constructor', 'instanceMethodTest']
console.log(Object.getOwnPropertyNames(TestClass.prototype));

//(1) ['instanceFieldTest']
console.log(Object.getOwnPropertyNames(TestInstance));

クラスメソッド・フィールドの列挙はクラスから、インスタンスメソッドの列挙はクラスのprototypeプロパティから、インスタンスフィールドの列挙はインスタンスからしかできないらしい。

2
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?