Отражение Javascript - получить все свойства объекта?

Как получить все свойства объекта, используя отражение в Javascript?

Ответы

Ответ 1

Прокрутите объект и возьмите все принадлежащие ему ключи, а не функция:

var properties = [];
for(var key in obj) {
    if(obj.hasOwnProperty(key) && typeof obj[key] !== 'function') {
        properties.push(key);
    }
}

Ответ 2

В современных браузерах, чтобы получить все имена свойств (а не только перечислимые свойства), вы должны использовать Object.getOwnPropertyNames...

var props = Object.getOwnPropertyNames(my_object)

Если вы не хотите перечислимых свойств, используйте Object.keys...

var props = Object.keys(my_object)

Ответ 3

var point = { x:5, y:8 };

for( var name in point ) {
    // name contains the property name that you want
    // point[name] contains the value
}

Ответ 4

В 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(' = ');
    });
};

Примечания: