はじめに
jsのclassに関して以下の情報を得たい
- getterの有無とその関数
- setterの有無とその関数
- methodの関数
- static methohd の関数
- class の宣言時の名前
- constructor の引数名
主に以下の関数を用いることで解析できます.
- Reflect.getOwnPropertyDescriptor
- Reflect.ownKeys
- Function.toString()
コード
クラス雛形用意
class Piyo {
constructor(argA, argB) {
console.log('@constructor :: ', Reflect.ownKeys(this));
this.memberA = argA;
}
get getA() {
console.log('@getA :: ', Reflect.ownKeys(this));
}
set setA(value) {
console.log('@setA :: ', Reflect.ownKeys(this));
}
static staticA() {
console.log('@staticA :: ', Reflect.ownKeys(this));
}
methodA() {
console.log('@methodA :: ', Reflect.ownKeys(this));
}
}
function listupTest(Hoge) {
let hoge = new Hoge('ARG_A', 'ARG_B');
// members: [ 'memberA' ]
console.log('members:', Reflect.ownKeys(hoge));
// methods: [ 'constructor', 'getA', 'setA', 'methodA' ]
console.log('methods:', Reflect.ownKeys(Hoge.prototype));
// statics: [ 'length', 'prototype', 'staticA', 'name' ]
console.log('statics:', Reflect.ownKeys(Hoge));
// name is: Piyo
console.log('name is:', Hoge.name);
let reflectHoge = k => Reflect.getOwnPropertyDescriptor(Hoge.prototype, k);
let res = {};
res.memberA = hoge.memberA;
res.methodA = reflectHoge('methodA').value;
res.getA = reflectHoge('getA').get;
res.setA = reflectHoge('setA').set;
res.staticA = Hoge.staticA;
res.props = getParams(Hoge, true);
// @methodA :: [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
res.methodA();
// @getA :: [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
res.getA();
// @setA :: [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
res.setA();
// @staticA :: [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
res.staticA();
// [ 'argA', 'argB' ]
console.log(res.props);
}
listupTest(Piyo);
参考
getParams
は以下を参考にしました.(constructor系functionに未対応だったのでそこの処理は追加しました)
https://qiita.com/chick307/items/1902fb32d252310d516d
function getParams(func, isConstructor = false) {
// コメントと空白を取り除いて正規化
let source = func.toString().replace(/\/\/.*$|\/\*[\s\S]*?\*\/|\s/gm, '');
if (!isConstructor) {
// 最初の丸かっこのもの
let params = source.match(/\((.*?)\)/)[1].split(',');
if (params.length === 1 && params[0] === '') return [];
return params;
}
let firstName = source.replace(/^.*?\{/, "").replace(/\(.*$/, "");
// constructor 系
if (firstName === "constructor") return getParams(func, false);
// babel系
if (firstName === "_classCallCheck") return getParams(func, false);
console.assert(false, "declare consturctor first!!");
}