2011-12-26 29 views
16

¿Cómo obtener todas las propiedades de un objeto utilizando la reflexión en Javascript?Reflejo de Javascript: ¿obtiene todas las propiedades de un objeto?

+0

posible duplicado de [la reflexión Javascript - toString genérico] (http://stackoverflow.com/questions/8638979/javascript-reflection-generic-tostring) –

+1

posible duplicado de [ Dado un objeto javascript arbitrario, ¿cómo puedo encontrar sus métodos?] (Http://stackoverflow.com/questions/3252406/given-an-arbitrary-javascript-object-how-can-i-find-its-methods) – hugomg

+4

@Brian Roach ¿por qué eso es un duplicado? no tiene nada que ver con toString! – IAdapter

Respuesta

24

bucle a través del objeto y tomar todas las claves que pertenece a la misma y no es una función:

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

En los navegadores modernos, para obtener todos los nombres de las propiedades (no sólo las propiedades enumerables), se 'd utilizar Object.getOwnPropertyNames ...

var props = Object.getOwnPropertyNames(my_object) 

Si no desea que las propiedades enumerables, tendrá que utilizar Object.keys ...

var props = Object.keys(my_object) 
3

JavaScript no tiene buenas herramientas integradas para la reflexión (introspección), por lo que es necesario hacerlo manualmente.

Al principio, aquí un código de una solución

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

Examine esta función en ejemplos reales.

Para incorporado en Array objeto

introspect(Array); 

Resultado:

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

Para matriz real (instancia de objeto de matriz)

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

Resultado:

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

¿Qué tal un objeto real?

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

Resultado:

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) 

Esta función también un buen trabajo con los módulos incorporados. Haga introspectivamente el módulo Math.

introspect(Math); 

Resultado

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

importa qué contaminar respuesta de código superfluo, intentar hacerlo usted mismo y ver los resultados

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

Para el código completo, también muestran la función "getFunctionParameters" (en módulo "functools.js"), ya que lo usó.

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

Notas:

  1. débilmente a prueba

  2. código completo aquí https://github.com/setivolkylany/nodejs-utils

  3. Buen recurso de ello tema http://www.2ality.com/2011/01/reflection-and-meta-programming-in.html

  4. usados ​​las características de la ES6

Cuestiones relacionadas