2010-07-27 16 views
6

Con una singola proprietà questo è abbastanza facile:selezione profonda dinamica di un oggetto JavaScript


var jsonobj = { 
    "test": "ok" 
} 
var propname = "test"; 
// Will alert "ok" 
alert(jsonobj[propname]); 

Ma quello che voglio fare è utilizzare una proprietà nidificato:


var jsonobj = { 
    "test": { 
     "test2": "ok" 
    } 
} 
var propname = "test.test2"; 
// Alerts undefined 
alert(jsonobj[propname]); 

non v'è alcun modo di selezionando una proprietà "dinamica" nidificata? So che posso fare jsonobj.test.test2, ma il problema è che propname può cambiare in una proprietà che va in profondità 1,2 o 3 livelli. (Ad esempio prova, test.test2, ...)

+0

Intendi dire JSON o un oggetto JavaScript? Non sono la stessa cosa. –

risposta

12
function resolve(cur, ns) { 

    var undef; 

    ns = ns.split('.'); 

    while (cur && ns[0]) 
     cur = cur[ns.shift()] || undef; 

    return cur; 

} 

Ad es

// 1: 
resolve({ 
    foo: { bar: 123 } 
}, 'foo.bar'); // => 123 


// 2: 
var complex = { 
    a: { 
     b: [ 
      document.createElement('div') 
     ] 
    } 
}; 

resolve(complex, 'a.b.0.nodeName'); // => DIV 

Il vantaggio nell'uso di questo è che non genera un errore se si tenta l'accesso a qualcosa che non esiste - è tornerà con grazia undefined.


EDIT:

Nel commento, Andy detto che questo non genera errori in cui ci si potrebbe aspettare a. Sono d'accordo che ottenere undefined è un po 'generico e non c'è modo di dire se il tuo valore è stato davvero risolto. Così, per rimediare a questo, provate questo:

var resolve = (function(){ 

    var UNRESOLVED = resolve.UNRESOLVED = {}; 
    return resolve; 

    function resolve(cur, ns) { 

     var undef; 

     ns = ns.split('.'); 

     while (cur && ns[0]) 
      cur = cur[ns.shift()] || undef; 

     if (cur === undef || ns[0]) { 
      return UNRESOLVED; 
     } 

     return cur; 

    } 

}()); 

che restituisca un oggetto irrisolti che possono essere controllati in questo modo:

var result = resolve(someObject, 'a.b.c'); 

if (result === resolve.UNRESOLVED) {...} 

Non è perfetto, ma è (IMO) il modo migliore per determinare uno spazio dei nomi non risolto senza dover generare errori. Se si desidera che gli errori, poi basta andare avanti con:

someObject.a.b.c; //... 
+1

Devo dire, mi piace molto questo. +1 – karim79

+0

Questo metodo funziona perfettamente per me, grazie mille! – user403428

+0

+1 Ben fatto! Mi è piaciuta anche la modifica "non definita" :) –

0

Questo funziona, ma piuttosto usa suckily eval quindi sono non raccomandando il suo uso:

var jsonobj = { 
    "test": { 
     "test2": "ok" 
    } 
} 
var propname = "test.test2"; 
alert(eval("jsonobj." + propname)); 
​ 

Provalo qui: http://jsfiddle.net/TAgsU/

+0

Otterrai comunque un errore TypeE se tenti di accedere a una proprietà con valore null/non definito. – James

+0

... oltre ad altre potenziali catastrofi a cui sopra potrebbe portare.Ecco perché ho * sconsigliato * it;) – karim79

1

È possibile scrivere una piccola funzione per dividere la stringa e quindi accedere a ciascun pezzo a turno. Per esempio:

function getProperty(propname, object) 
{ 
    var props = propname.split('.'); 
    var obj = object; 
    for (var i=0; i<props.length; i++) 
    { 
     obj = obj[props[i]]; 
    } 
    return obj; 
} 

Ovviamente nees un po 'di codice in più per verificare la presenza di oggetti nulli, proprietà valide, ecc

3

Ho anche appena implementato questo utilizzando una funzione ricorsiva interna in questo modo:

function get(obj, ns) {    

    function recurse(o, props) { 
     if (props.length === 0) { 
      return o; 
     } 
     if (!o) { 
      return undefined; 
     } 
     return recurse(o[props.shift()], props); 
    } 

    return recurse(obj, ns.split('.')); 
} 

Ciò restituirà il valore profondo della proprietà specificata dal ns param, altrimenti ritornerà sempre indefinito se non esiste o ci sono problemi lungo il percorso.

+0

nota che l'approccio ricorsivo, sebbene più carino, è più lento di un approccio iterativo (almeno nei miei test) – sym3tri

Problemi correlati