web-dev-qa-db-ja.com

オブジェクトのすべてのプロパティを取得するにはどうすればよいですか?

JavaScriptでリフレクションを使用してオブジェクトのすべてのプロパティを取得するにはどうすればよいですか?

22
IAdapter

オブジェクトをループして、オブジェクトに属し、関数ではないすべてのキーを取得します。

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

最近のブラウザでは、(列挙可能なプロパティだけでなく)すべてのプロパティ名を取得するには、Object.getOwnPropertyNames ..を使用します。

var props = Object.getOwnPropertyNames(my_object)

列挙可能なプロパティが必要ない場合は、Object.keys ..を使用します。

var props = Object.keys(my_object)
22
user1106925

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]}      parameters 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の機能を使用

7
PADYMKO
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
Uri