Ответ 1
Прокрутите объект и возьмите все принадлежащие ему ключи, а не функция:
var properties = [];
for(var key in obj) {
if(obj.hasOwnProperty(key) && typeof obj[key] !== 'function') {
properties.push(key);
}
}
Как получить все свойства объекта, используя отражение в Javascript?
Прокрутите объект и возьмите все принадлежащие ему ключи, а не функция:
var properties = [];
for(var key in obj) {
if(obj.hasOwnProperty(key) && typeof obj[key] !== 'function') {
properties.push(key);
}
}
В современных браузерах, чтобы получить все имена свойств (а не только перечислимые свойства), вы должны использовать Object.getOwnPropertyNames
...
var props = Object.getOwnPropertyNames(my_object)
Если вы не хотите перечислимых свойств, используйте Object.keys
...
var props = Object.keys(my_object)
var point = { x:5, y:8 };
for( var name in point ) {
// name contains the property name that you want
// point[name] contains the value
}
В 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})`);
}
};
Изучите эту функцию на реальных примерах.
Для встроенного массива объектов
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 ()
Для реального массива (экземпляр массива объектов)
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