2013-02-08 6 views
51

In meinem Code, beschäftige ich mich mit einer Reihe, die einige Einträge mit vielen Objekten verschachtelt innerhalb eines hat einen anderen, wo, wie manche nicht. Es sieht etwa wie folgt:Wie zu vermeiden, kann nicht Eigenschaft von undefinierten Fehlern lesen?

// where this array is hundreds of entries long, with a mix 
// of the two examples given 
var test = [{'a':{'b':{'c':"foo"}}}, {'a': "bar"}]; 

Das ist mir Probleme geben, weil ich manchmal durch das Array zu durchlaufen müssen, und die Inkonsistenz wirft mir Fehler wie so:

for (i=0; i<test.length; i++) { 
    // ok on i==0, but 'cannot read property of undefined' on i==1 
    console.log(a.b.c); 
} 

Ich bin mir bewusst, dass ich if(a.b){ console.log(a.b.c)} sagen, aber das ist außerordentlich mühsam in Fällen, in denen bis zu 5 oder 6 Objekten sind ineinander verschachtelt. Gibt es eine andere (einfacher) Art und Weise, dass ich es kann nur die console.log tun, wenn es existiert, aber ohne einen Fehler zu werfen?

+3

Der Fehler ist wahrscheinlich eine regelmäßige Ausnahme Javascript, so versuchen, die 'try..catch' Aussage. Das heißt, ein Array, das wild heterogene Elemente enthält, sieht für mich wie ein Designproblem aus. – millimoose

+3

Wenn Ihre Struktur in den Elementen nicht konsistent ist, was stimmt dann nicht mit der Existenzprüfung? Eigentlich würde ich 'if (" b "in einem &&" c "in a.b)' verwenden. Es kann "langweilig" sein, aber das ist, was Sie für Inkonsistenz bekommen ... normale Logik. – Ian

+2

Warum würden Sie auf nicht vorhandene Eigenschaften zugreifen? Warum wissen Sie nicht, wie die Objekte aussehen? – Bergi

Antwort

31

Was Sie tun, löst eine Ausnahme (und zu Recht).

können Sie tun immer

try{ 
    window.a.b.c 
}catch(e){ 
    console.log("YO",e) 
} 

Aber ich würde, anstatt denken Sie an Ihre Anwendungsfall nicht.

Warum greifen Sie auf Daten zu, 6 verschachtelte Ebenen, denen Sie nicht vertraut sind? Welcher Use Case rechtfertigt dies?

Normalerweise möchten Sie tatsächlich validieren, um was für ein Objekt es sich handelt.

Außerdem sollten Sie auf eine Randnotiz keine Anweisungen wie if(a.b) verwenden, da es false zurückgibt, wenn a.b 0 ist oder auch wenn es "0" ist. Überprüfen Sie stattdessen, ob a.b !== undefined

+1

In Bezug auf Ihre erste Bearbeitung: Es ist gerechtfertigt; Ich beschäftige mich mit strukturierten JSON-Datenbankeinträgen, so dass die Objekte mehrere Ebenen von Feldern skalieren (dh entries.users.messages.date usw., wo nicht alle Fälle Daten eingegeben haben) – Ari

+0

"es wird wahr zurückgegeben, wenn ab 0 ist "- Nein. 'typeof ab ===" undefined "&& ab! = null' - unnötig, den zweiten Teil nach dem ersten zu machen, und es macht mehr Sinn, einfach zu tun, wenn (" b "in a)' – Ian

+0

@Ian ja, ich offensichtlich bedeutete es umgekehrt, es wird falsch zurückgeben, auch wenn ab "0" ist. Netter Fang –

11

Wenn ich Ihre Frage richtig verstehe, möchten Sie den sichersten Weg, um festzustellen, ob ein Objekt eine Eigenschaft enthält.

Der einfachste Weg ist die Verwendung der Anweisung "in".

window.a = "aString"; 
//window should have 'a' property 
//lets test if it exists 
if ("a" in window){ 
    //true 
} 

if ("b" in window){ 
    //false 
} 

Natürlich können Sie nisten können diese so tief wie Sie

if ("a" in window.b.c) { } 

Nicht sicher wollen, ob das hilft.

+0

Das war nützlich für mich, danke –

+1

Sie können nicht so sicher wie möglich verschachteln. Was ist, wenn 'window.b' nicht definiert ist? Sie erhalten einen Typfehler: 'Kann 'in' Operator nicht verwenden, um nach 'c' in undefined ' – Trevor

7

Wenn Sie lodash verwenden, können Sie ihre "hat" -Funktion verwenden. Es ähnelt dem nativen "in", erlaubt aber Pfade.

var testObject = {a: {b: {c: 'walrus'}}}; 
if(_.has(testObject, 'a.b.c')) { 
    //Safely access your walrus here 
} 
1

Ich verwende undefsafe religiös. Es testet jede Ebene in Ihr Objekt, bis es entweder den von Ihnen angeforderten Wert erhält, oder es gibt "undefined" zurück. Aber niemals Fehler.

+2

zu suchen, das lodash' _.get' ähnelt – Filype

+0

Guter Ruf! Immer noch nützlich, wenn Sie die anderen Funktionen von lodash nicht benötigen. – martinedwards

2

Dies ist ein häufiges Problem, wenn mit tiefem oder komplexem JSON-Objekt arbeiten, so dass ich versuche try/catch oder Einbetten mehr Kontrollen zu vermeiden, die den Code nicht lesbar machen würden, verwende ich in die Regel dieses kleine Stück Code in allen meiner procect zu mach den Job.

/* ex: getProperty(myObj,'aze.xyz',0) // return myObj.aze.xyz safely 
* accepts array for property names: 
*  getProperty(myObj,['aze','xyz'],{value: null}) 
*/ 
function getProperty(obj, props, defaultValue) { 
    var res, isvoid = function(x){return typeof x === "undefined" || x === null;} 
    if(!isvoid(obj)){ 
     if(isvoid(props)) props = []; 
     if(typeof props === "string") props = props.trim().split("."); 
     if(props.constructor === Array){ 
      res = props.length>1 ? getProperty(obj[props.shift()],props,defaultValue) : obj[props[0]]; 
     } 
    } 
    return typeof res === "undefined" ? defaultValue: res; 
} 
13

Eine schnelle Abhilfe ist mit einer try/catch-Helferfunktion mit ES6 arrow function:

function getSafe(fn) { 
    try { 
     return fn(); 
    } catch (e) { 
     return undefined; 
    } 
} 

// use it like this 
getSafe(() => obj.a.lot.of.properties); 

this article für Details.

+2

Das ist wirklich erstaunlich !! – Trevor

1

Versuchen Sie dies. Wenn a.b undefiend ist, wird die if-Anweisung ohne Ausnahme verlassen.

if (a.b && a.b.c) { 
    console.log(a.b.c); 
} 
Verwandte Themen