如何获取对象的所有属性?

时间:2011-12-26 20:46:33

标签: javascript object reflection properties

如何使用JavaScript中的反射获取对象的所有属性?

4 个答案:

答案 0 :(得分:29)

遍历对象并获取属于它的每个键,而不是 功能:

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

答案 1 :(得分:20)

在现代浏览器中,要获取所有属性名称(不仅仅是可枚举属性),您可以使用Object.getOwnPropertyNames ...

var props = Object.getOwnPropertyNames(my_object)

如果您不想要可枚举的属性,则可以使用Object.keys ...

var props = Object.keys(my_object)

答案 2 :(得分:7)

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 ()

对于实数组(对象数组的实例)

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)

此功能也可以很好地与内置模块配合使用。内省模拟数学。

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

备注:

  1. 弱测试

  2. 此处的完整代码https://github.com/setivolkylany/nodejs-utils

  3. 关于它的主题资源http://www.2ality.com/2011/01/reflection-and-meta-programming-in.html

  4. 使用了ES6的功能

答案 3 :(得分:4)

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

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