В JavaScript нет хороших встроенных инструментов для отражения (самоанализа), поэтому вам нужно сделать это вручную.
Сначала здесь приведен код решения
/**
* Display details about an object at run-time
* @param {[any]} target Any object
* @return Nothing, all information will be display
*/
const introspect = (target) => {
// get type of a target
const typeTarget = typeof target;
// variable for type attribute of the target
let typeAttr;
// for properties and methods of the target
let properties = [];
let methods = [];
// if target is array, keep names all enumerable properties, simple put - numbers of indexes
// otherwise set to null
const enumerableProperties = Array.isArray(target) ? Object.keys(target) : null;
// determination functions and properties of the target by a parent object
Object.getOwnPropertyNames(Object.getPrototypeOf(target)).forEach((name) => {
if (typeof target[name] === 'function') {
methods.push(name);
} else if (target.hasOwnProperty(name) && properties.indexOf(name) === -1) {
properties.push(name);
}
});
// determination other functions and properties of the target
// filter it, if a name already added or if it is an array - filter all values of the indexes
Object.getOwnPropertyNames(target).forEach((name) => {
if (enumerableProperties !== null && enumerableProperties.indexOf(name) !== -1) {
return;
}
if (typeof target[name] === 'function') {
methods.push(name);
} else if (target.hasOwnProperty(name) && properties.indexOf(name) === -1) {
properties.push(name);
}
});
// order properties and methods by name in reverse
properties = properties.reverse();
methods = methods.reverse();
// display an obtained information by groups
console.log(`${typeTarget}: "${target}"`);
console.log(`\n\tProperties: ${properties.length}\n\t------------------`);
for (let i = properties.length - 1; i >= 0; i -= 1) {
typeAttr = typeof target[properties[i]];
console.log(`\t\t${properties[i]} --> ${typeAttr}`);
}
console.log(`\n\tMethods: ${methods.length}\n\t------------------`);
for (let i = methods.length - 1; i >= 0; i -= 1) {
let args = functools.getFunctionParameters(target[methods[i]]);
args = args.join(', ');
console.log(`\t\t${methods[i]} (${args})`);
}
};
Изучите эту функцию на реальных примерах.
Для встроенного объекта Array
introspect(Array);
Результат:
function: "function Array() { [native code] }"
Properties: 5
------------------
length --> number
name --> string
arguments --> object
caller --> object
prototype --> object
Methods: 8
------------------
apply ()
bind ()
call ()
toString ()
constructor ()
isArray ()
from ()
of ()
Для реального массива (экземпляр объекта Array)
introspect([-10, '20', true, []]);
Результат:
object: "-10,20,true,"
Properties: 1
------------------
length --> number
Methods: 29
------------------
constructor ()
toString ()
toLocaleString ()
join ()
pop ()
push ()
reverse ()
shift ()
unshift ()
slice ()
splice ()
sort ()
filter ()
forEach ()
some ()
every ()
map ()
indexOf ()
lastIndexOf ()
reduce ()
reduceRight ()
copyWithin ()
find ()
findIndex ()
fill ()
includes ()
entries ()
keys ()
concat ()
А как насчет реального объекта?
introspect({
aa: 1,
bb: true,
cc: [],
dd: {},
c: (z, a= 2) => {},
b: function(z = 1, a=2) {},
d: function(b, zzz) {},
});
Результат:
object: "[object Object]"
Properties: 4
------------------
aa --> number
bb --> boolean
cc --> object
dd --> object
Methods: 14
------------------
hasOwnProperty ()
constructor ()
toString ()
toLocaleString ()
valueOf ()
isPrototypeOf ()
propertyIsEnumerable ()
__defineGetter__ ()
__lookupGetter__ ()
__defineSetter__ ()
__lookupSetter__ ()
c (z, a = 2)
b (z = 1, a = 2)
d (b, zzz)
Эта функция также хорошо работаетсо встроенными модулями.Сделайте интроспекцию по модулю Math.
introspect(Math);
Результат
object: "[object Math]"
Properties: 8
------------------
E --> number
LN10 --> number
LN2 --> number
LOG2E --> number
LOG10E --> number
PI --> number
SQRT1_2 --> number
SQRT2 --> number
Methods: 46
------------------
hasOwnProperty ()
constructor ()
toString ()
toLocaleString ()
valueOf ()
isPrototypeOf ()
propertyIsEnumerable ()
__defineGetter__ ()
__lookupGetter__ ()
__defineSetter__ ()
__lookupSetter__ ()
acos ()
asin ()
atan ()
ceil ()
clz32 ()
floor ()
fround ()
imul ()
max ()
min ()
round ()
sqrt ()
trunc ()
random ()
abs ()
exp ()
log ()
atan2 ()
pow ()
sign ()
asinh ()
acosh ()
atanh ()
hypot ()
cbrt ()
cos ()
sin ()
tan ()
sinh ()
cosh ()
tanh ()
log10 ()
log2 ()
log1p ()
expm1 ()
Что за загрязнение ответьте на лишний код, попробуйте сделать это самостоятельно и посмотрите результаты
introspect(34.2313);
introspect(true);
introspect(Date);
introspect((new Date()));
introspect(String);
introspect('text');
Для полногокод, я также показываю функцию "getFunctionParameters" (в модуле "functools.js"), так как она использовалась.
/**
* Return array paraments of a function
* @param {[function]} func function
* @return {[array]} parammeters the functions
*
*/
const getFunctionParameters = (func) => {
if (typeof func !== 'function') {
throw new Error('A argument is not function.');
}
const args = func.toString().match(/\((.*)\)/)[1];
return args.split(',').map((arg) => {
if (arg.indexOf('=') === -1) return arg.trim();
return arg
.split('=')
.map(val => val.trim())
.join(' = ');
});
};
Примечания:
Слабо проверено
Полный код здесь https://github.com/setivolkylany/nodejs-utils
Хороший ресурс по этой теме http://www.2ality.com/2011/01/reflection-and-meta-programming-in.html
Использованы функции ES6