2011-12-26 17 views
16

Come ottenere tutto ottenere tutte le proprietà di un oggetto utilizzando la riflessione in Javascript?Riflesso Javascript - ottieni tutte le proprietà di un oggetto?

+0

possibile duplicato del [riflessione Javascript - toString generico] (http://stackoverflow.com/questions/8638979/javascript-reflection-generic-tostring) –

+1

possibile duplicato del [ Dato un oggetto javascript arbitrario, come posso trovare i suoi metodi?] (Http://stackoverflow.com/questions/3252406/given-an-arbitrary-javascript-object-how-can-i-find-its-methods) – hugomg

+4

@ Roian Roach perché questo è duplicato? non ha nulla a che fare con toString! – IAdapter

risposta

24

Loop attraverso l'oggetto e prendere ogni chiave che appartiene ad esso e non è una funzione:

var properties = []; 
for(var key in obj) { 
    if(obj.hasOwnProperty(key) && typeof obj[key] !== 'function') { 
     properties.push(key); 
    } 
} 
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 
} 
16

Nel browser moderni, per ottenere tutti i nomi di proprietà (non solo le proprietà enumerabili), è 'd utilizzare Object.getOwnPropertyNames ...

var props = Object.getOwnPropertyNames(my_object) 

Se non si desidera che le proprietà enumerabili, utilizza Object.keys ...

var props = Object.keys(my_object) 
3

JavaScript non ha strumenti validi per la riflessione (introspezione), quindi è necessario farlo manualmente.

In un primo momento, ecco un codice di una soluzione

/** 
* 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})`); 
    } 
}; 

Esaminate questa funzione su esempi reali.

Per oggetti incorporata Array

introspect(Array); 

risultati:

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

Per matrice reale (istanza di oggetto Array)

introspect([-10, '20', true, []]); 

risultati:

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

Che dire di un oggetto reale?

introspect({ 
    aa: 1, 
    bb: true, 
    cc: [], 
    dd: {}, 
    c: (z, a= 2) => {}, 
    b: function(z = 1, a=2) {}, 
    d: function(b, zzz) {}, 
}); 

Risultato:

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) 

Questa funzione anche un buon lavoro con i moduli incorporati. Rendi introspettivo il modulo Math.

introspect(Math); 

Risultato

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

Materia ciò inquinare risposta codice superfluo, provare fai da te e vedere i risultati

introspect(34.2313); 
introspect(true); 
introspect(Date); 
introspect((new Date())); 
introspect(String); 
introspect('text'); 

Per il codice completo, mi mostrano anche la funzione "getFunctionParameters" (in modulo "functools.js"), dal momento che lo ha usato.

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

Note:

  1. debolmente testati

  2. codice completo qui https://github.com/setivolkylany/nodejs-utils

  3. buona risorsa su di esso argomento http://www.2ality.com/2011/01/reflection-and-meta-programming-in.html

  4. usate le caratteristiche del ES6

Problemi correlati