2011-12-26 54 views
16

Làm sao để có được tất cả các thuộc tính của một đối tượng sử dụng sự phản chiếu trong Javascript?Phản chiếu Javascript - nhận tất cả các thuộc tính của một đối tượng?

+0

trùng lặp có thể xảy ra [Javascript phản ánh - generic toString] (http://stackoverflow.com/questions/8638979/javascript-reflection-generic-tostring) –

+1

thể trùng lặp của [ Cho một đối tượng javascript tùy ý, làm cách nào tôi có thể tìm thấy các phương thức của nó?] (Http://stackoverflow.com/questions/3252406/given-an-arbitrary-javascript-object-how-can-i-find-its-methods) – hugomg

+4

@Brian Roach tại sao thats một nhân đôi? nó không liên quan gì đến toString! – IAdapter

Trả lời

24

Vòng qua các đối tượng và tận dụng mọi quan trọng mà thuộc về nó và không phải là một hàm:

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

Trong trình duyệt hiện đại, để có được tất cả tên thuộc tính (không chỉ tính đếm được), bạn muốn sử dụng Object.getOwnPropertyNames ...

var props = Object.getOwnPropertyNames(my_object) 

Nếu bạn không muốn tính đếm được, bạn muốn sử dụng Object.keys ...

var props = Object.keys(my_object) 
3

JavaScript không có công cụ tích hợp, tốt cho sự phản chiếu (nội tâm), vì vậy bạn cần thực hiện thủ công.

Lúc đầu, đây là một quy tắc ứng một giải pháp

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

Kiểm tra chức năng này trên ví dụ thực tế.

Đối với built-in đối tượng Array

introspect(Array); 

Kết quả:

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

Đối với mảng sản (thể hiện của đối tượng Array)

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

Kết quả:

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

Còn đối tượng thực thì sao?

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

Kết quả:

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) 

Chức năng này cũng hoạt động tốt với các module tích hợp. Hãy nhìn vào mô-đun Toán học.

introspect(Math); 

quả

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

Matter gì gây ô nhiễm trả lời đang thừa, hãy thử làm điều đó cho mình và xem kết quả

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

Đối với mã đầy đủ, tôi cũng cho thấy chức năng "getFunctionParameters" (trong mô-đun "functools.js"), vì nó đã sử dụng nó.

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

Ghi chú:

  1. yếu thử nghiệm

  2. Full mã ở đây https://github.com/setivolkylany/nodejs-utils

  3. Tài nguyên tốt về nó đề http://www.2ality.com/2011/01/reflection-and-meta-programming-in.html

  4. sử dụng các tính năng của ES6

Các vấn đề liên quan