2016-08-04 67 views
-1

Zuerst ein wenig Kontext (Sie können diesen Teil überspringen, wenn Sie sich auf Code konzentrieren möchten).sicher von einem Objekt in einer Knotenanwendung erhalten

Ich trat einem neuen Projekt bei, das in einer nodeJS Plattform integriert werden wird. Unser Team hat Erfahrung mit JEE Enterprise Web Apps. Das bildet unseren Hintergrund. Dieses neue Projekt wird REST-APIs verwenden, einige Daten aggregieren, einige Geschäftslogiken implementieren und diese Daten an den Frontend-Endverbraucher weitergeben. Eine Art leichter Microservice-Architektur.

Einige Mitarbeiter begann an dem Projekt zu arbeiten, und ich fand es, dass wir in den Quellcode tun eine Menge Code-Schnipsel wie if (foo != null && foo.property != null) {return foo.property.value;}

Foo soll wird an ein als Argument übergeben ein Objekt sein Funktion, die diese Art von Test implementieren würde.

Ein Schnipsel Beispiel wird mehr sprechen.

Nehmen wir an, das ist die Antwort einer API, die ich konsumiere. Ich möchte eine kleine Funktion schreiben, die statusValue zurückgeben würde, wenn das Objekt existiert, wenn es nicht null oder nicht definiert ist, nicht leer und die Eigenschaft existiert und nicht leer oder leer ist.

var response = { 
    "services":[], 
    "metadata": { 
    "status": "statusValue" 
    } 
}; 

Das ist, wie es für jetzt ist:

function getStatusValue(response) { 
    if (response != null && response.metadata != null) { 
     return response.metadata.status; 
    } 
}; 

Was würde als beste JS Praxis in Betracht gezogen werden, dass zur Umsetzung (wir verwenden auch lodash so ist es vielleicht eine bessere Option lodash Interna zu verwenden dafür). Ich befürchte nur, dass wir unsere Java-Gewohnheiten umsetzen.

Grundsätzlich würde ich gerne wissen, wie für null, undefined, empty, blank sicher zu überprüfen (wenn das Sinn macht). Was wäre die Best Practice von JS im Jahr 2016 mit Bibliotheken wie lodash und so weiter?

+0

Zum einen können Sie '! = Null 'weglassen, weil' null'/'undefined' falsch ist – qxz

+0

Ich benutze' if (obj && obj.prop) '. Um 'undefiniertes' Objekt zu verhindern, können Sie' strict mode' verwenden. –

+0

Ja, wir verwenden den strikten Modus – anchnk

Antwort

0

Wenn Sie nach Eigenschaften eines Objekts suchen, ist es nicht ausreichend, nach einer losen Gleichheit zu suchen. null ist nicht genug.

Lose Gleichheit (==) verwendet Typ Hinting in JavaScript, die versucht, die Mitglieder in einen gemeinsamen Typ zu konvertieren, der dann für die Bestimmung verwendet werden kann, ob sie gleich sind oder nicht. Aus diesem Grund schreiben Best Practices für JavaScript vor, dass strikte Gleichheit (===) immer verwendet werden soll, um Rand-Case-Szenarien oder unbekanntes Verhalten beim Prüfen auf Werte oder Typen zu vermeiden. Sie können weitere Informationen über lose vs strikte Gleichheit finden Sie hier:

Während dies in Ihrer Funktion nicht ein Must-Have ist, ist es eine gute Praxis zu folgen und sich als Gewohnheit entwickeln, so dass beim späteren Code die Implikationen der losen Gleichheit (==) vermieden werden könnten (zB Vermeiden von '3' == 3, wenn eine Zahl oder ein String-Typ erwartet wird).

zwar ein Nachteil der Sprache, die von einigen als unter Verwendung von null als Kontrolle für undefined in Absicht ähnlich ist, ist aber tatsächlich in dem Code auszudrücken gemeint, dass der Coder einen object (oder ihr Fehlen) zur Verfügung gestellt werden erwartet, anstelle eines primitiven Typs (number, string, boolean, function). Dies unterscheidet sich von Java oder einer anderen typisierten Sprache, wobei null für Object Typ definierte Variablen verwendet wird; , aber in JavaScript gibt es keine Einschränkung auf den angegebenen Typ.

Sie können weitere Informationen über null bei MDN erfahren: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null

In der Praxis und vor allem, wenn mit Werten zu tun, die außerhalb einer Einheit kommen -, die mit dem Fall eines API ist - ist eine bewährte Methode angesehen um zu überprüfen, ob der Typ ein object ist, um sicherzustellen, dass es Eigenschaften hat.

Obwohl Ihr Code nicht inkorrekt ist, zeigt er doch, dass den Best Practices wenig Aufmerksamkeit geschenkt wird, was letztendlich dazu führen wird, dass Buggy-Code geschrieben wird.

Mein Vorschlag für Ihren Code, nach Best Practices und unabhängig von jeder Bibliothek ist:

function getStatusValue(response) { 
     // must be of type `object`, to have properties. 
    if (typeof response === 'object' && 
     // any variable of type `object` might be `null`, so exclude that. 
     response !== null && 
     // `metadata` property must be of type `object`, to have properties. 
     typeof response.metadata !== 'object' && 
     // `metadata` is of type `object`, check for not being `null`. 
     response.metadata !== null) { 


       // `status` property is expected to be a string, given by the API spec 
      if (typeof response.metadata.status === 'string' && 
       // on strings, we can access the `length` property to check if empty string (0 chars). 
       response.metadata.status.length > 0) { 
       // all good, return `status` property. 
       return response.metadata.status; 
      } else { 
      // `status` property is either not a string, or an empty string (''). 
      } 


    } else { 
     // invalid `response` object. 
    } 
} 

Auch könnte es einfacher sein, oder aus irgendwelchen Bibliotheken, die Sie für ein überprüfen integrieren, eine Funktion zum Erstellen gültiges Objekt; so etwas wie _.isObject oder dies:

function isObject(o) { 
    return (typeof o === 'object' && o !== null); 
} 

, die Sie später in dem oben verwendet werden könnten, wie so snipped:

function getStatusValue(response) { 
    if (isObject(response) && isObject(response.metadata)) { 

      if (typeof response.metadata.status === 'string' && 
       response.metadata.status.length > 0) { 
       return response.metadata.status; 
      } else { 
      // `status` property is either not a string, or an empty string (''). 
      } 
    } else { 
     // invalid `response` object. 
    } 
} 

Als letzten Gedanken, wie es ist deutlich sichtbar, Best Practices folgende nicht erhöht die Größe des Codes, aber der Vorteil ist, dass der resultierende Code ist viel sicherer, mit weniger Chancen, Ausnahmen zu werfen (root von vielen Abstürzen App), einfacher zu kooperieren, und einfacher zu Tests/Coverage für zu bauen.

0

Mit Lodash können Sie die _.isNil(response) Funktion dokumentiert here verwenden.

Im Allgemeinen würde ich eine Variable wie folgt überprüfen:

if (typeof x !== 'undefined' && x !== null) { 
    // x has some value 
} 

Sie sollten nicht prüfen, ob x === undefined denn wenn x nicht definiert ist, können Sie einen dereferenzieren Fehler bekommen.

0

Hier ist eine (prägnante) Art und Weise mit nur JS, so etwas zu tun:

var obj = ...; 
var val = obj && obj.prop && obj.prop.val; 

valundefined/null wenn entweder obj oder obj.prop sind sein werden; andernfalls wird es obj.prop.val sein.

Dies funktioniert wegen der Kurzschlussauswertung von &&. Sein literales Verhalten ist folgendes: Wenn der erste Operand falsch ist, wird der erste Operand ausgewertet. Ansonsten wird es zum zweiten ausgewertet. Dies funktioniert wie erwartet für boolesche Operationen, aber wie Sie sehen können, kann es bei Objekten nützlich sein.

|| hat ähnliches Verhalten. Zum Beispiel können Sie es verwenden, um einen Wert zu erhalten, oder einen Standardwert, wenn der Wert Falsey (zB null) ist:

var val2 = val || "not found"; 

Beachten Sie, dass dies zu "not found" bewerten würde, wenn val ist etwas Falsey, einschließlich 0 oder "".

+0

Was ist, wenn 'obj.prop.val === false'? – Ben

+0

Dann wäre 'val'' false'. – qxz

+0

Manchmal ist diese Überprüfung nicht korrekt, z. 'obj.prop.val = 0'. Aber ich benutze auch diese Überprüfung :) –

0

Ich würde implementieren diese die folgende Funktion:

var response = { 
 
    "services":[], 
 
    "metadata": { 
 
    "status": "statusValue" 
 
    } 
 
}; 
 

 
function getStatusValue(res) { 
 
    if (res && res.metadata) 
 
    return res.metadata.status || 'not found'; 
 
    else 
 
    return 'not found'; 
 
} 
 

 
console.log(getStatusValue(response));

Die if Anweisung false wenn res oder res.metadata sind undefined zurückkehren und wenn sie beide vorhanden ist, wird es res.metadata.statusnur zurückkehren Wenn es definiert ist oder 0, sonst wird 'not found' zurückgegeben.

+0

Beachten Sie, dass dies "nicht gefunden" zurückgeben würde, wenn "res.metadata.status === 0" – qxz

+0

Das ist die Lösung, die ich für jetzt verwendet habe. Ich schätze, ich muss eine Testsuite einrichten, um zu sehen, wie sie sich mit all den Situationen verhält, die ich bekommen kann – anchnk