2012-11-28 3 views
23

E 'possibile ottenere il nome della proprietà dell'oggetto come stringaottenere l'oggetto nome della proprietà come una stringa

person = {}; 
person.first_name = 'Jack'; 
person.last_name = 'Trades'; 
person.address = {}; 
person.address.street = 'Factory 1'; 
person.address.country = 'USA'; 

mi piacerebbe utilizzarlo in questo modo:

var pn = propName(person.address.country); // should return 'country' or 'person.address.country' 
var pn = propName(person.first_name);  // should return 'first_name' or 'person.first_name' 

Grazie in anticipo

NOTA: questo codice è esattamente quello che sto cercando. Capisco che suoni anche stupidi, ma non lo è.

Questo è quello che voglio fare con esso.

HTML

person = {}; 
person.id_first_name = 'Jack'; 
person.id_last_name = 'Trades'; 
person.address = {}; 
person.address.id_address = 'Factory 1'; 
person.address.id_country = 'USA'; 


extPort.postMessage 
(
    { 
    message : MSG_ACTION, 
    propName(person.first_name): person.first_name 
    } 
}; 

---------------------- RISPOSTA ------------ -----------

Ottenuto grazie a ibu. Indicò la strada giusta e ho usato una funzione ricorsiva

var res = ''; 

function propName(prop, value) { 
    for (var i in prop) { 
     if (typeof prop[i] == 'object') { 
      if (propName(prop[i], value)) { 
       return res; 
      } 
     } else { 
      if (prop[i] == value) { 
       res = i; 
       return res; 
      } 
     } 
    } 
    return undefined; 
} 

var pn = propName(person, person.first_name); // returns 'first_name' 
var pn = propName(person, person.address.country); // returns 'country' 

DEMO: http://jsbin.com/iyabal/1/edit

+7

Sono confuso ... perché vuoi che il nome della proprietà restituisca la stessa cosa che hai alimentato? Conosci già il nome della proprietà quindi ... Se stai cercando un modo per iterare attraverso le proprietà, puoi usare la notazione delle parentesi e scorrere i tasti, poiché le proprietà sono anche indici hash – RonaldBarzell

+0

Devi anche passare un riferimento a l'oggetto nella funzione. –

+0

Non automaticamente. La stringa a cui fa riferimento la proprietà 'country' non sa nulla circa l'oggetto' address', e l'oggetto a cui fa riferimento la proprietà 'address' non sa nulla sull'oggetto' person'. –

risposta

2

Sì, è possibile, con un piccolo cambiamento.

function propName(prop, value){ 
    for(var i in prop) { 
     if (prop[i] == value){ 
      return i; 
     } 
    } 
    return false; 
} 

ora è possibile ottenere il valore in questo modo:

var pn = propName(person,person.first_name); 
// pn = "first_name"; 

Nota io non sono sicuro di quello che può essere utilizzato per.

Altra nota non funziona molto bene con oggetti nidificati. ma poi di nuovo, vedi la prima nota.

+9

Questo presuppone che non due proprietà avranno lo stesso valore in un oggetto. – Sampson

+0

... e non è sufficiente per oggetti nidificati. – Christophe

+0

Aumenta solo di un livello. – Ivan

0

No, non è possibile.

Immaginate questo:

person.age = 42; 
person.favoriteNumber = 42; 

var pn = propName(person.age) 
// == propName(42) 
// == propName(person.favoriteNumber); 

Il riferimento al nome della proprietà è semplicemente perso in questo processo.

+1

Perché il downvote ? Qualche contro-argomento? –

0

È possibile creare un metodo namespacing per l'oggetto. Il metodo dovrà modificare l'oggetto in modo che le stringhe diventino un oggetto invece di contenere due proprietà, una value e una _namespace.

DEMO: http://jsfiddle.net/y4Y8p/1/

var namespace = function(root, name) { 
    root._namespace = name; 
    function ns(obj) { 
     for(var i in obj) { 
      var a = obj._namespace.split('.') 
      if (a.length) { 
       a.push(i); 
      } 
      if(typeof obj[i] == 'object') { 
       obj[i]._namespace = a.join('.'); 
       ns(obj[i]); 
       return; 
      } 
      if(typeof obj[i] == 'string') { 
       var str = obj[i].toString(); 
       obj[i] = { 
        _namespace: a.join('.'), 
        value: str 
       }; 
      } 
     } 
    } 
    ns(root); 
}; 

namespace(person, 'person'); 

console.log(person.address.street._namespace) // person.address.street 
console.log(person.address.street.value) // 'Factory 1' 

Così ora si può fare:

var o = { message: MSG_ACTION }; 
o[ person.first_name._namespace ] = person.first_name.value; 

extPort.postMessage(o); 
+0

Sono rimasto affascinato da questa risposta, quindi ho iniziato a hackerarlo per cercare di trovare un approccio più pulito. ecco cosa ho scoperto finora, cosa ne pensi: http://jsfiddle.net/y4Y8p/17/ –

+0

@JasonSperske bello, ma non è ricorsivo quindi funziona solo a 3 livelli di profondità: http: // jsfiddle.net/y4Y8p/18/ – David

+0

http://jsfiddle.net/y4Y8p/22/ provalo ora :) Ci sono ancora problemi più grandi, come prendere tutti i valori e convertirli in stringhe, ma questo è un po 'divertente codice per giocare con –

3

Puoi avvolgere la vostra proprietà in una funzione e poi convertire la funzione in una stringa e ottenere la proprietà fuori di esso.

Ad esempio:

function getPropertyName(propertyFunction) { 
    return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1]; 
} 

Poi, per usarlo:

var myObj = { 
    myProperty: "testing" 
}; 

getPropertyName(function() { myObj.myProperty; }); // myProperty 

Sembra un po 'più bello con ES6 sintassi:

getPropertyName(() => myObj.myProperty); 

Anche se io non sono sicuro al 100% ciò restituirebbe una stringa simile a function() { ... }. L'ho usato solo attraverso un transpiler.

+4

Basta fare attenzione quando si utilizza questo con minifaction ... –

+0

Grande .. mi ha aiutato .. Grazie –

12

Conosco una pratica ottimale che utilizza Object.keys(your_object). Analizzerà il nome della proprietà dell'array per te. Esempio:

var person = { firstName: 'John', lastName: 'Cena', age: '30' }; 
var listPropertyNames = Object.keys(person); //["firstName", "lastName", "age"] 

Spero che questo esempio sia utile per voi.

+5

Dovrebbe essere 'chiavi' in minuscolo. – madprops

0

Sono nella stessa situazione.

Qui è il tuo modo per farlo fare utilizzando Lodash o UnderScore biblioteca, con un limite di valore per essere unico:

var myObject = { 
'a': 1, 
'b': 2, 
'c': 3 
} 
_.findKey(myObject, function(curValue) { return myObject.a === curValue }); 

Plain JavaScript

function getPropAsString(source, value){ 
    var keys = Object.keys(source); 

    var curIndex, 
     total, 
     foundKey; 

    for(curIndex = 0, total = keys.length; curIndex < total; curIndex++){ 
     var curKey = keys[ curIndex ]; 
     if (source[ curKey ] === value){ 
      foundKey = curKey; 
      break; 
     } 
    } 

    return foundKey; 
} 

var myObject = { 
'a': 1, 
'b': 2, 
'c': 3 
} 
getPropAsString(myObject, myObject.a) 

Ma, preferirei risolvere il codice come soluzione. Un esempio:

var myObject = { 
'a': {key:'a', value:1}, 
'b': {key:'b', value:2}, 
'c': {key:'c', value:3} 
} 

console.log(myObject.a.key) 
0

C'è modo di farlo utilizzando le chiusure. Esempio con sintassi ES6

var person = {}; 
person.firstname = 'Jack'; 
person.address = "123 Street"; 

function getPropertyName(obj, expression) { 
    var res = {}; 
    Object.keys(obj).map(k => { res[k] =() => k; }); 
    return expression(res)(); 
} 

let result = getPropertyName(person, o => o.address); 
console.log(result); // Output: 'address'