Vorwort Freunde, die am Frontend arbeiten, müssen auf Situationen gestoßen sein, in denen die vom Backend zurückgegebenen Daten in mehreren Schichten verschachtelt sind. Wenn ich den Wert eines tiefen Objekts abrufen möchte, führe ich Schicht für Schicht Nicht-Leer-Prüfungen durch, um Fehler zu vermeiden, beispielsweise: const obj = { Waren: Name: "a", Schlagworte: { Name: 'Schnell', ID: 1, tagTyp: { Name: "Bezeichnung" } } } } Wenn ich tagType.name abrufen muss, lautet die Beurteilung wie folgt wenn (obj.goods !== null && obj.goods.tags !== null && obj.goods.tags.tagType !== null) { } Wenn der Attributname lang ist, ist der Code unlesbar. Natürlich hat ECMAScript 2020 ?. eingeführt, um dieses Problem zu lösen: let name = obj?.Waren?.Tags?.Tagestyp?.Name; Aber wie geht man mit Browsern um, die nicht mit ES2020 kompatibel sind? TextStudenten, die Lodash verwendet haben, wissen möglicherweise, dass es in Lodash eine Get-Methode gibt. Auf der offiziellen Website heißt es: _.get(Objekt, Pfad, [Standardwert]) Holen Sie sich den Wert entsprechend dem Pfad des Objekts. Wenn der aufgelöste Wert nicht definiert ist, wird er durch den Standardwert ersetzt. Parameter
Beispielvar Objekt = { 'a': [{ 'b': { 'c': 3 } }] }; _.get(Objekt, 'a[0].b.c'); // => 3 _.get(Objekt, ['a', '0', 'b', 'c']); // => 3 _.get(Objekt, 'abc', 'Standard'); // => 'Standard' Dies löst das Problem, aber (ich fürchte, es gibt ein „aber“) Was passiert, wenn ich die Lodash-Bibliothek aus verschiedenen Gründen, beispielsweise aufgrund von Projekt- oder Unternehmensanforderungen, nicht verwenden kann? Sehen wir uns nun an, wie lodash implementiert wird. Können wir nicht einfach den Code extrahieren? Dann können wir wieder fröhlich Steine verschieben~~ Lodash-Implementierung:Funktion get(Objekt, Pfad, Standardwert) { const Ergebnis = Objekt == null? undefiniert: baseGet(Objekt, Pfad) Rückgabeergebnis === undefiniert? Standardwert: Ergebnis } Was wir hier tun, ist sehr einfach. Schauen wir uns zuerst die Rückgabe an. Wenn das Objekt den Standardwert zurückgibt, befindet sich der Kerncode in baseGet. Schauen wir uns also die Implementierung von baseGet an. Funktion baseGet(Objekt, Pfad) { //Konvertiere den Eingabestring path in ein Array, Pfad = castPath(Pfad, Objekt) lass Index = 0 Konstante Länge = Pfadlänge // Durchlaufe das Array, um alle Objektebenen abzurufen while (object != null && index < length) { Objekt = Objekt[toKey(Pfad[index++])] // toKey-Methode} return (Index && Index == Länge)? Objekt: undefiniert } Hier verwenden wir zwei Funktionen: castPath (konvertiert den Eingabepfad in ein Array) und toKey (konvertiert den tatsächlichen Schlüssel). Tokey-Funktion:/** Wird als Referenz für verschiedene `Number`-Konstanten verwendet. */ Konstante UNENDLICHKEIT = 1 / 0 /** * Wandelt „Wert“ in einen String-Schlüssel um, wenn es sich nicht um einen String oder ein Symbol handelt. * * @Privat * @param {*} Wert Der zu prüfende Wert. * @returns {string|symbol} Gibt den Schlüssel zurück. */ Funktion toKey(Wert) { wenn (Typ des Wertes === 'Zeichenfolge' || istSymbol(Wert)) { Rückgabewert } const Ergebnis = `${Wert}` return (Ergebnis == '0' und (1 / Wert) == -UNENDLICH) ? '-0' : Ergebnis } Hier werden im Wesentlichen zwei Dinge erledigt.
Die Funktion isSymbol wird hier auch verwendet, um zu bestimmen, ob es sich um einen Symboltyp handelt. Der Code wird hier nicht veröffentlicht. Interessierte Studenten können den Lodash-Quellcode überprüfen. castPath-Funktion:importiere isKey aus './isKey.js' importiere stringToPath aus „./stringToPath.js“ /** * Wandelt „Wert“ in ein Pfad-Array um, wenn es keins ist. * * @Privat * @param {*} Wert Der zu prüfende Wert. * @param {Object} [Objekt] Das Objekt, dessen Schlüssel abgefragt werden sollen. * @returns {Array} Gibt das Array mit dem Pfad der gegossenen Eigenschaft zurück. */ Funktion castPath(Wert, Objekt) { wenn (Array.isArray(Wert)) { Rückgabewert } returniere isKey(Wert, Objekt) ? [Wert] : stringToPath(Wert) } castPath konvertiert hauptsächlich den Eingabepfad in ein Array, um ihn auf die nachfolgende Durchquerung zum Abrufen tiefer Objekte vorzubereiten. Hier werden isKey() und stringToPath() verwendet. isKey ist eine relativ einfache Funktion, um zu bestimmen, ob der aktuelle Wert der Schlüssel eines Objekts ist. stringToPath behandelt hauptsächlich den Fall, in dem der Eingabepfad eine Zeichenfolge ist, z. B.: 'abc[0].d' stringToPath-Funktion:importiere memoizeCapped aus „./memoizeCapped.js“ const charCodeOfDot = '.'.charCodeAt(0) const reEscapeChar = /\(\)?/g const rePropName = RegExp( // Findet eine Übereinstimmung mit allem, was kein Punkt oder keine Klammer ist. '[^.[\]]+' + '|' + // Oder passen Sie die Eigenschaftsnamen in Klammern an. '\[(?:' + //Passt auf einen Ausdruck, der kein String ist. '([^"'][^[]*)' + '|' + // Oder Zeichenfolgen abgleichen (unterstützt das Escapen von Zeichen). '(["'])((?:(?!\2)[^\\]|\\.)*?)\2' + ')\]'+ '|' + // Oder "" als Leerzeichen zwischen aufeinanderfolgenden Punkten oder leeren Klammern abgleichen. '(?=(?:\.|\[\])(?:\.|\[\]|$))' , 'G') /** * Konvertiert „String“ in ein Eigenschaftspfad-Array. * * @Privat * @param {string} string Der zu konvertierende String. * @returns {Array} Gibt das Eigenschaftspfad-Array zurück. */ const stringToPath = memoizeCapped((string) => { const Ergebnis = [] wenn (string.charCodeAt(0) === charCodeOfDot) { Ergebnis.push('') } string.replace(rePropName, (Übereinstimmung, Ausdruck, Anführungszeichen, Teilzeichenfolge) => { let key = match wenn (Zitat) { Schlüssel = Teilstring.replace(reEscapeChar, '$1') } sonst wenn (Ausdruck) { Schlüssel = Ausdruck.trim() } Ergebnis.push(Schlüssel) }) Ergebnis zurückgeben }) Hier schließen wir hauptsächlich die . und [] im Pfad aus, analysieren den echten Schlüssel und fügen ihn dem Array hinzu memoizeCapped-Funktion:importiere Memoize aus „../memoize.js“ /** Wird als maximale Memoize-Cachegröße verwendet. */ const MAX_MEMOIZE_SIZE = 500 /** * Eine spezielle Version von `memoize`, die die gespeicherten Daten der Funktion löscht. * Cache, wenn „MAX_MEMOIZE_SIZE“ überschritten wird. * * @Privat * @param {Function} func Die Funktion, deren Ausgabe gespeichert werden soll. * @returns {Function} Gibt die neue gespeicherte Funktion zurück. */ Funktion memoizeCapped(Funktion) { const Ergebnis = memoize(Funktion, (Schlüssel) => { const { cache } = Ergebnis wenn (cache.size === MAX_MEMOIZE_SIZE) { cache.löschen() } Eingabetaste }) Ergebnis zurückgeben } Export-Standard-MemoizeCapped Hier ist ein Limit für den zwischengespeicherten Schlüssel, der Cache wird gelöscht, wenn er 500 erreicht Memoize-Funktion:Funktion memoize(Funktion, Resolver) { wenn (Typ der Funktion !== 'Funktion' || (Resolver != null und Typ des Resolvers !== 'Funktion')) { throw new TypeError('Eine Funktion erwartet') } const memoized = Funktion(...args) { const Schlüssel = Resolver? Resolver.apply(diese, Argumente) : Argumente[0] const cache = memoized.cache wenn (cache.hat(Schlüssel)) { returniere cache.get(Schlüssel) } const Ergebnis = func.apply(diese, Argumente) memoized.cache = cache.set(Schlüssel, Ergebnis) || Cache Ergebnis zurückgeben } memoized.cache = neu (memoize.Cache || Map) Rückkehr auswendig gelernt } memoize.Cache = Karte Eigentlich verstehe ich die letzten beiden Funktionen nicht ganz. Wenn der Eingabepfad „abc“ ist, können wir ihn dann nicht einfach in ein Array umwandeln? Warum Closures zum Caching verwenden? Ich hoffe, dass mir jemand, der sich damit auskennt, eine Antwort geben kann. Da der Quellcode viele Funktionen verwendet und in verschiedenen Dateien liegt, habe ich diese vereinfacht. Der vollständige Code lautet wie folgt:/** * Ruft den Wert unter `path` von `object` ab. Wenn der aufgelöste Wert * „undefined“, stattdessen wird „defaultValue“ zurückgegeben. * @Beispiel * const Objekt = { 'a': [{ 'b': { 'c': 3 } }] } * * bekomme(Objekt, 'a[0].b.c') * // => 3 * * bekomme(Objekt, ['a', '0', 'b', 'c']) * // => 3 * * bekomme(Objekt, 'abc', 'Standard') * // => 'Standard' */ safeGet (Objekt, Pfad, Standardwert) { Ergebnis lassen wenn (Objekt != null) { if (!Array.isArray(Pfad)) { const type = Typ des Pfads wenn (Typ === 'Zahl' || Typ === 'Boolesch' || Pfad == null || /^\w*$/.test(Pfad) || !(/.|[(?:[^[]]*|(["'])(?:(?!\1)[^\]|\.)*?\1)]/.test(Pfad)) || (Objekt != null && Pfad in Objekt(Objekt))) { Pfad = [Pfad] } anders { const Ergebnis = [] wenn (Pfad.charCodeAt(0) === '.'.charCodeAt(0)) { Ergebnis.push('') } const rePropName = RegExp( // Findet eine Übereinstimmung mit allem, was kein Punkt oder keine Klammer ist. '[^.[\]]+|\[(?:([^"'][^[]*)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))' , 'G') Pfad.ersetzen(rePropName, (Übereinstimmung, Ausdruck, Zitat, Teilzeichenfolge) => { let key = match wenn (Zitat) { Schlüssel = Teilstring.replace(/\(\)?/g, '$1') } sonst wenn (Ausdruck) { Schlüssel = Ausdruck.trim() } Ergebnis.push(Schlüssel) }) Pfad = Ergebnis } } lass Index = 0 Konstante Länge = Pfadlänge const toKey = (Wert) => { wenn (Typ des Wertes === 'Zeichenfolge') { Rückgabewert } const Ergebnis = `${Wert}` return (Ergebnis === '0' && (1 / Wert) === -(1 / 0)) ? '-0' : Ergebnis } während (Objekt != null und Index < Länge) { Objekt = Objekt[toKey(Pfad[Index++])] } Ergebnis = (Index && Index === Länge)? Objekt: undefiniert } Rückgabeergebnis === undefiniert? Standardwert: Ergebnis } Der Code ist von lodash übernommen Quellen:
ZusammenfassenDies ist das Ende dieses Artikels zum sicheren Abrufen von Objekten auf tiefer Ebene in Js. Weitere relevante Inhalte zum Abrufen von Objekten auf tiefer Ebene in Js finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
>>: So verwenden Sie Nginx zum Erstellen eines statischen Ressourcenservers
Vorwort Dieser Artikel stellt hauptsächlich die d...
Vorwort Ich habe vor kurzem eine Feuerwerksanimat...
Lösung 1: Verwenden Sie bedingten Import im HTML-...
Inhaltsverzeichnis 1. Grundlage des Responsive-Pr...
Es ist auch sehr einfach, Django-Projekte mit Doc...
1. Problembeschreibung <br />Wenn JS verwen...
Kerncode /*-------------------------------- Suche...
1 Einleitung Ein guter Programmierer sollte über ...
Laut Nullwerten bedeutet der Wert Null in MySQL l...
Methode 1: Verwenden Sie den Befehl SET PASSWORD ...
Als ich heute die Anmeldeseite geschrieben habe, ...
1. Installieren Sie xshell6 2. Stellen Sie eine S...
Vorwort Beim Anlegen der Primär- und Fremdschlüss...
In diesem Artikel wird hauptsächlich die wunderba...
Installieren Sie Apache aus der Quelle 1. Laden S...