Wenn ich einen Verweis auf ein Objekt habe:
var test = {};
das wird möglicherweise (aber nicht sofort) verschachtelte Objekte haben, so etwas wie:
{level1: {level2: {level3: "level3"}}};
Was ist der beste Weg, um das Vorhandensein von Eigentum in tief verschachtelten Objekten zu überprüfen?
alert(test.level1);
ergibt undefined
, aberalert(test.level1.level2.level3);
scheitert .
Ich mache gerade so etwas:
if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
alert(test.level1.level2.level3);
}
aber ich habe mich gefragt, ob es einen besseren Weg gibt.
javascript
object
properties
nested
user113716
quelle
quelle
Antworten:
Sie müssen es Schritt für Schritt tun, wenn Sie keine möchten,
TypeError
denn wenn eines der Mitgliedernull
oder istundefined
eine Ausnahme ausgelöst wird, ist und Sie versuchen, auf ein Mitglied zuzugreifen.Sie können entweder einfach
catch
die Ausnahme oder eine Funktion zum Testen der Existenz mehrerer Ebenen erstellen:ES6 UPDATE:
Hier ist eine kürzere Version der ursprünglichen Funktion, die ES6-Funktionen und Rekursion verwendet (auch in richtigen Tail-Call- Form):
Wenn Sie jedoch den Wert einer verschachtelten Eigenschaft abrufen und nicht nur ihre Existenz überprüfen möchten, finden Sie hier eine einfache einzeilige Funktion:
Mit der obigen Funktion können Sie den Wert verschachtelter Eigenschaften abrufen, andernfalls wird zurückgegeben
undefined
.UPDATE 2019-10-17:
Der optionale Verkettungsvorschlag hat Stufe 3 des ECMAScript-Ausschussprozesses erreicht. Auf diese Weise können Sie mithilfe des Tokens
?.
, des neuen optionalen Verkettungsoperators , sicher auf tief verschachtelte Eigenschaften zugreifen :Wenn eine der Ebenen ist, auf die zugegriffen wird,
null
oderundefined
der Ausdruck sichundefined
von selbst auflöst .Mit dem Vorschlag können Sie auch Methodenaufrufe sicher verarbeiten:
Der obige Ausdruck erzeugt,
undefined
wennobj
,obj.level1
oderobj.level1.method
sindnull
oderundefined
, sonst ruft er die Funktion auf.Sie können mit dieser Funktion mit Babel über das optionale Verkettungs-Plugin spielen .Seit Babel 7.8.0 wird ES2020 standardmäßig unterstützt
Überprüfen Sie dieses Beispiel auf der Babel REPL.
🎉🎉UPDATE: Dezember 2019 🎉🎉
Der optionale Verkettungsvorschlag erreichte schließlich Stufe 4 in der Sitzung des TC39-Ausschusses im Dezember 2019. Dies bedeutet, dass diese Funktion Teil des ECMAScript 2020- Standards sein wird.
quelle
arguments
ist eigentlich kein Array.Array.prototype.slice.call(arguments)
konvertiert es in ein formales Array. Learnvar obj = arguments[0];
und zu beginnen,var i = 1
anstatt dasarguments
Objekt zu kopierenargs
Variablendeklaration entfernt und...args
als zweites Argument für diecheckNested
Methode verwendet werden. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Hier ist ein Muster, das ich von Oliver Steele aufgenommen habe :
In der Tat ist dieser ganze Artikel eine Diskussion darüber, wie Sie dies in Javascript tun können. Er beschließt, die obige Syntax (die nicht so schwer zu lesen ist, wenn man sich erst einmal daran gewöhnt hat) als Redewendung zu verwenden.
quelle
(test || {})
ist, dass wenn der Test undefiniert ist, Sie es tun({}.level1 || {})
. Natürlich{}.level1
ist undefiniert, das heißt, Sie tun es{}.level2
und so weiter.test
es nicht deklariert ist, wird es einen ReferenceError geben , aber das ist kein Problem, denn wenn es nicht deklariert ist, muss ein Fehler behoben werden, also ist der Fehler eine gute Sache.if(test.level1 && test.level1.level2 && test.level1.level2.level3)
Aktualisieren
Sieht so aus, als hätte lodash für alle Ihre Bedürfnisse nach verschachtelten Immobilien hinzugefügt
_.get
.https://lodash.com/docs#get
Vorherige Antwort
Benutzer von lodash können sich an lodash.contrib erfreuen, das über einige Methoden verfügt, mit denen dieses Problem behoben werden kann .
getPath
Unterschrift:
_.getPath(obj:Object, ks:String|Array)
Ruft den Wert in einer beliebigen Tiefe in einem verschachtelten Objekt basierend auf dem Pfad ab, der durch die angegebenen Schlüssel beschrieben wird. Schlüssel können als Array oder als durch Punkte getrennte Zeichenfolge angegeben werden. Gibt zurück,
undefined
wenn der Pfad nicht erreicht werden kann.quelle
function isPathDefined(object, path) { return typeof _.getPath(object, path) !== 'undefined'; }
_.get(countries, 'greece.sparta.playwright', 'default'); // → 'default' _.has(countries, 'greece.spart.playwright') // → false
var url = _.get(e, 'currentTarget.myurl', null) || _.get(e, 'currentTarget.attributes.myurl.nodeValue', null) || null
Ich habe Leistungstests (danke cdMinix für das Hinzufügen von lodash) für einige der zu dieser Frage vorgeschlagenen Vorschläge mit den unten aufgeführten Ergebnissen durchgeführt.
Objektverpackung (von Oliver Steele) - 34% - am schnellsten
Ursprüngliche Lösung (in Frage vorgeschlagen) - 45%
checkNested - 50%
get_if_exist - 52%
validChain - 54%
objHasKeys - 63%
nestedPropertyExists - 69%
_.get - 72%
deeptest - 86%
traurige Clowns - 100% - am langsamsten
quelle
_.get()
? Wie performant ist es im Vergleich zu diesen Antworten?reduce
odertry/catch
aus Bequemlichkeit entscheiden.try { test.level1.level2.level3 } catch (e) { // some logger e }
Sie können eine Objekteigenschaft in jeder Tiefe lesen, wenn Sie den Namen wie eine Zeichenfolge behandeln :
't.level1.level2.level3'
.Es wird zurückgegeben,
undefined
wenn eines der Segmente istundefined
.quelle
Wenn Sie in ES6 Umgebung Codierung (oder mit 6to5 ) , dann können Sie die Vorteile der nehmen Pfeil Funktion Syntax:
In Bezug auf die Leistung gibt es keine Leistungseinbußen für die Verwendung von
try..catch
Block, wenn die Eigenschaft festgelegt ist. Wenn die Eigenschaft nicht festgelegt ist, wirkt sich dies auf die Leistung aus.Betrachten Sie einfach
_.has
:quelle
try-catch
Ansatz ist die beste Antwort. Es gibt einen philosophischen Unterschied zwischen der Abfrage eines Objekts nach seinem Typ und der Annahme, dass die API vorhanden ist, und dem entsprechenden Fehlschlagen, wenn dies nicht der Fall ist. Letzteres ist in lose typisierten Sprachen besser geeignet. Siehe stackoverflow.com/a/408305/2419669 . Dertry-catch
Ansatz ist auch viel klarer alsif (foo && foo.bar && foo.bar.baz && foo.bar.baz.qux) { ... }
.wie wäre es mit
quelle
hasOwnProperty()
n-mal anzurufen ?ES6 Antwort, gründlich getestet :)
→ siehe Codepen mit vollständiger Testabdeckung
quelle
===
die verschiedenen Falsys und füge einen Test hinzu. Wenn Sie eine bessere Idee haben, lassen Sie es mich wissen.)false
. Und dann möchten Sie vielleicht einen Wert in Ihrem Objekt haben, auf den gesetzt istundefined
(ich weiß, dass es seltsam ist, aber es ist JS). Ich habe einen positiven falschen Wert eingestellt auf'Prop not Found'
:const hasTruthyProp = prop => prop === 'Prop not found' ? false : true const path = obj => path => path.reduce((obj, prop) => { return obj && obj.hasOwnProperty(prop) ? obj[prop] : 'Prop not found' }, obj) const myFunc = compose(hasTruthyProp, path(obj))
Sie können auch den optionalen Verkettungsvorschlag tc39 zusammen mit babel 7 - verwenden. tc39-Vorschlag verwenden
Code würde so aussehen:
quelle
Ich habe einen rekursiven Ansatz versucht:
Die
! keys.length ||
Rekursion wird beendet, sodass die Funktion nicht ausgeführt wird, ohne dass noch Tasten zum Testen übrig sind. Tests:Ich verwende es, um eine benutzerfreundliche HTML-Ansicht einer Reihe von Objekten mit unbekannten Schlüsseln / Werten zu drucken, z.
quelle
Ich denke, das folgende Skript bietet eine besser lesbare Darstellung.
deklariere eine Funktion:
dann benutze es so:
Ich nenne es "traurige Clown-Technik", weil sie das Zeichen o (
BEARBEITEN:
Hier ist eine Version für TypeScript
Es gibt Typprüfungen zur Kompilierungszeit (sowie die Intellisense, wenn Sie ein Tool wie Visual Studio verwenden).
Die Verwendung ist die gleiche:
aber diesmal funktioniert Intellisense!
Außerdem können Sie einen Standardwert festlegen:
quelle
°0o <°(())))><
Object
Typ nicht kennst . +1.Erstellen Sie ein globales
function
und verwenden Sie es im gesamten ProjektVersuche dies
wenn Bedingung
quelle
Ein einfacher Weg ist folgender:
Das
try/catch
fängt die Fälle ab, in denen eines der übergeordneten Objekte wie test, test.level1, test.level1.level2 nicht definiert ist.quelle
Ich habe kein Beispiel für jemanden gesehen, der Proxies verwendet
Also habe ich mir meine eigene ausgedacht. Das Tolle daran ist, dass Sie keine Zeichenfolgen interpolieren müssen. Sie können tatsächlich eine kettenfähige
Objektfunktion zurückgebenund einige magische Dinge damit tun. Sie können sogar Funktionen aufrufen und Array-Indizes abrufen, um nach tiefen Objekten zu suchenCode-Snippet anzeigen
Der obige Code funktioniert gut für synchrone Inhalte. Aber wie würden Sie etwas Asynchrones wie diesen Ajax-Aufruf testen? Wie testest du das? Was ist, wenn die Antwort nicht json ist, wenn ein 500-http-Fehler zurückgegeben wird?
Sicher, Sie könnten async / await verwenden, um einige Rückrufe zu entfernen. Aber was wäre, wenn Sie es noch magischer machen könnten? etwas, das so aussieht:
Sie fragen sich wahrscheinlich, wo sich alle Versprechen und
.then
Ketten befinden ... dies könnte für alles, was Sie wissen, blockieren ... aber mit der gleichen Proxy-Technik mit Versprechen können Sie tatsächlich tief verschachtelte komplexe Pfade auf ihre Existenz testen, ohne jemals eine einzige Funktion zu schreibenCode-Snippet anzeigen
quelle
Basierend auf dieser Antwort habe ich diese generische Funktion entwickelt, mit
ES2015
der das Problem gelöst werden kannquelle
function validChain (object, path) { return path.split('.').reduce((a, b) => (a || { })[b], object) !== undefined }
Ich habe eine kleine Funktion erstellt, um verschachtelte Objekteigenschaften sicher abzurufen.
Oder eine einfachere, aber etwas unlesbare Version:
Oder noch kürzer, aber ohne Rückfall auf die falsche Flagge:
Ich habe Test mit:
Und hier sind einige Tests:
Um den gesamten Code mit der Dokumentation und den Tests zu sehen, die ich ausprobiert habe, können Sie meinen Github-Inhalt überprüfen: https://gist.github.com/vsambor/3df9ad75ff3de489bbcb7b8c60beebf4#file-javascriptgetnestedvalues-js
quelle
Eine kürzere ES5-Version der hervorragenden Antwort von @ CMS:
Mit einem ähnlichen Test:
quelle
checkObjHasKeys(test, ['level1', 'level2', 'asdf', 'asdf']);
success = false;
zureturn false
. Sie sollten aussteigen, sobald Sie wissen, dass es kaputt geht. Nichts Tieferes kann existieren, wenn es null oder undefiniert ist. Dies würde die Fehler auf den tiefer verschachtelten Elementen verhindern, da sie offensichtlich auch nicht vorhanden sind.Ich denke, das ist eine leichte Verbesserung (wird ein 1-Liner):
Dies funktioniert, weil der Operator && den endgültigen Operanden zurückgibt, den er ausgewertet hat (und der kurzgeschlossen wird).
quelle
Ich habe nach dem Wert gesucht, der zurückgegeben werden soll, wenn die Eigenschaft vorhanden ist, daher habe ich die Antwort von CMS oben geändert. Folgendes habe ich mir ausgedacht:
quelle
Die von CMS gegebene Antwort funktioniert auch mit der folgenden Änderung für Nullprüfungen einwandfrei
quelle
Ausgehend von dieser Antwort wurden folgende Optionen ausgearbeitet . Gleicher Baum für beide:
Stoppen Sie die Suche, wenn Sie nicht definiert sind
Stellen Sie sicher, dass jede Ebene einzeln ist
quelle
Ich weiß, dass diese Frage alt ist, aber ich wollte eine Erweiterung anbieten, indem ich sie allen Objekten hinzufüge. Ich weiß, dass die Leute dazu neigen, den Objektprototyp für erweiterte Objektfunktionen zu verwenden, aber ich finde nichts einfacher als dies. Außerdem ist dies jetzt mit der Object.defineProperty- Methode zulässig .
Um nun auf eine Eigenschaft in einem Objekt zu testen, können Sie einfach Folgendes tun:
Hier ist eine jsfiddle zum Testen, und insbesondere enthält sie eine jQuery, die unterbrochen wird, wenn Sie den Object.prototype direkt ändern, weil die Eigenschaft aufzählbar wird. Dies sollte mit Bibliotheken von Drittanbietern gut funktionieren.
quelle
Dies funktioniert mit allen Objekten und Arrays :)
Ex:
Dies ist meine verbesserte Version von Brians Antwort
Ich habe _has als Eigenschaftsnamen verwendet, da dies zu Konflikten mit vorhandenen has-Eigenschaften führen kann ( z. B. maps).
Hier ist die Geige
quelle
Hier ist meine Meinung dazu - die meisten dieser Lösungen ignorieren den Fall eines verschachtelten Arrays wie in:
Ich möchte vielleicht nachsehen
obj.l2[0].k
Mit der folgenden Funktion können Sie dies tun
deeptest('l2[0].k',obj)
Die Funktion gibt true zurück, wenn das Objekt vorhanden ist, andernfalls false
quelle
Jetzt können wir auch
reduce
verschachtelte Schlüssel durchlaufen:quelle
Sie können dies mit der rekursiven Funktion tun. Dies funktioniert auch dann, wenn Sie nicht alle Namen der verschachtelten Objektschlüssel kennen.
quelle
Hier auf der Codeabode (safeRead) gibt es eine Funktion , die dies auf sichere Weise erledigt ... dh
Wenn eine Eigenschaft null oder undefiniert ist, wird eine leere Zeichenfolge zurückgegeben
quelle
Basierend auf einem vorherigen Kommentar ist hier eine andere Version, in der das Hauptobjekt ebenfalls nicht definiert werden konnte:
quelle
Ich habe meine eigene Funktion geschrieben, die den gewünschten Pfad einnimmt und eine gute und eine schlechte Rückruffunktion hat.
Verwendungszweck:
quelle
quelle