Heim >Web-Frontend >js-Tutorial >Best Practices in modernem JavaScript – Teil 2
Im ersten Teil dieses Artikels haben wir die Grundlagen des modernen JavaScript und einige wesentliche Best Practices untersucht, um saubereren und effizienteren Code zu schreiben. Aber als Entwickler wissen wir, dass es immer mehr zu lernen und zu verbessern gibt.
Bei der Arbeit mit Objekten oder verschachtelten Strukturen müssen wir manchmal prüfen, ob eine Eigenschaft vorhanden ist, bevor wir versuchen, darauf zuzugreifen. Der optionale Verkettungsoperator (?.) ist ein leistungsstarkes Tool, das diese Aufgabe vereinfacht und Fehler beim Zugriff auf Eigenschaften von Null- oder undefinierten Werten vermeidet.
Stellen Sie sich vor, Sie haben eine komplexe Objektstruktur und sind sich nicht sicher, ob bestimmte Eigenschaften darin vorhanden sind. Ohne optionale Verkettung müssten Sie bei jedem Schritt manuelle Überprüfungen durchführen, was Ihren Code länger und weniger lesbar machen kann. Mit dem ?-Operator können Sie sicher auf Eigenschaften zugreifen und undefiniert werden, wenn eine der Zwischeneigenschaften nicht vorhanden ist.
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Da das Produkt in diesem Fall nicht über die Preiseigenschaft verfügt, gibt die optionale Verkettung undefiniert zurück, anstatt einen Fehler zu generieren.
Stellen Sie sich vor, Sie haben eine Liste von Produkten mit unterschiedlichen Eigenschaften, von denen einige möglicherweise leer oder undefiniert sind:
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
In diesem Beispiel können wir durch die optionale Verkettung Fehler beim Zugriff auf „product.details.tax“ vermeiden, selbst wenn „details“ null ist oder nicht vorhanden ist.
Optionale Verkettung kann auch mit Funktionen verwendet werden, was sehr nützlich ist, wenn Sie Funktionen haben, die möglicherweise nicht für ein Objekt definiert sind:
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Hier ist die getAge-Funktion undefiniert (sie ist null), aber sie gibt keinen Fehler aus, sondern gibt nur undefiniert zurück.
Wenn Sie mit asynchronen Vorgängen in JavaScript arbeiten, wie z. B. dem Abrufen von Daten von einer API oder dem Lesen von Dateien, kann die async/await-Syntax Ihr bester Freund sein. Anstatt Versprechen mit .then() und .catch() zu verwenden, können Sie mit async/await asynchronen Code auf sauberere und besser lesbare Weise schreiben, ähnlich wie wir synchronen Code schreiben würden.
Angenommen, wir arbeiten mit einer API, die Daten zurückgibt. Durch die Verwendung von async/await anstelle von .then() ist der Ablauf viel einfacher zu verfolgen:
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Stellen Sie sich vor, Sie haben eine Webseite, auf der Sie Benutzerinformationen von einer API anzeigen müssen. Hier ist ein Beispiel dafür, wie Sie mit async/await die Daten abrufen und an die Schnittstelle rendern können:
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
Gibt ein Array mit allen Werten der Eigenschaften eines Objekts zurück. Perfekt, wenn Sie nur die Werte ohne Schlüssel benötigen.
Beispiel:
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Dies ist die vielseitigste Methode. Gibt ein Array von Arrays zurück, wobei jedes Unterarray einen Schlüssel und den entsprechenden Wert enthält. Dies ist nützlich, wenn Sie in einem einzigen Vorgang sowohl mit Schlüsseln als auch mit Werten arbeiten möchten.
Beispiel:
async function obtenerDatos() { try { const respuesta = await fetch('https://api.ejemplo.com/datos'); if (!respuesta.ok) { throw new Error('Error al obtener los datos'); } const datos = await respuesta.json(); console.log(datos); } catch (error) { console.error('Error:', error.message); } }
Wussten Sie, dass Sie diese Methoden mit for...of kombinieren können, um Ihren Code noch sauberer zu machen? Hier ist ein Beispiel mit Object.entries():
Beispiel:
// Función para obtener y mostrar los datos de usuarios async function obtenerUsuarios() { try { const respuesta = await fetch('https://api.ejemplo.com/usuarios'); if (!respuesta.ok) { throw new Error('No se pudieron cargar los usuarios'); } const usuarios = await respuesta.json(); mostrarUsuariosEnUI(usuarios); } catch (error) { console.error('Hubo un problema con la carga de los usuarios:', error); alert('Error al cargar los usuarios. Intenta más tarde.'); } } // Función para renderizar usuarios en el HTML function mostrarUsuariosEnUI(usuarios) { const contenedor = document.getElementById('contenedor-usuarios'); contenedor.innerHTML = usuarios.map(usuario => ` <div> <h3> ¿Qué mejoramos con async/await? </h3> <ol> <li> <strong>Manejo claro de errores:</strong> Usamos try/catch para capturar cualquier error que pueda ocurrir durante la obtención de datos, ya sea un problema con la red o con la API.</li> <li> <strong>Código más legible:</strong> La estructura de await hace que el flujo del código se lea de manera secuencial, como si fuera código sincrónico.</li> <li> <strong>Evita el anidamiento:</strong> Con async/await puedes evitar los callbacks anidados (el famoso "callback hell") y las promesas encadenadas.</li> </ol> <p>Usar async/await no solo mejora la calidad de tu código, sino que también hace que sea mucho más fácil depurar y mantener proyectos a largo plazo. ¡Es una herramienta poderosa que deberías incorporar siempre que trabajes con asincronía en JavaScript!</p> <h2> 10. Métodos modernos para objetos </h2> <p>Cuando trabajamos con objetos en JavaScript, es común que necesitemos iterar sobre las claves y los valores, o incluso extraer solo las claves o valores. Los métodos modernos como Object.entries(), Object.values() y Object.keys() hacen que estas tareas sean mucho más fáciles y legibles.</p> <h3> Object.keys() </h3> <p>Este método devuelve un array con todas las claves de un objeto. Es útil cuando solo necesitas acceder a las claves y no a los valores.</p> <p><strong>Ejemplo:</strong><br> </p> <pre class="brush:php;toolbar:false">const obj = { a: 1, b: 2, c: 3 }; const claves = Object.keys(obj); console.log(claves); // ["a", "b", "c"]
Dieser Ansatz ist sauberer und einfacher zu lesen, insbesondere wenn Sie mit großen oder komplexen Objekten arbeiten.
Wenn Sie Werte mit Schlüsseln verknüpfen müssen, die keine Zeichenfolgen oder Symbole sind, verwenden Sie Map. Es ist robuster und behält die Art und Reihenfolge der Schlüssel bei.
Beispiel:
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Symbole sind eine JavaScript-Funktion, mit der Sie eindeutige und unveränderliche Schlüssel erstellen können. Dies macht sie zu einem leistungsstarken Werkzeug, wenn wir sicherstellen müssen, dass ein Wert nicht versehentlich überschrieben oder darauf zugegriffen wird. Auf Symbole kann nicht mit Methoden wie Object.keys(), for...in oder JSON.stringify() zugegriffen werden, was sie perfekt für private oder „versteckte“ Werte macht.
Wenn wir Eigenschaften eines Objekts mithilfe von Schlüsseln wie Textzeichenfolgen erstellen, können diese leicht manipuliert oder überschrieben werden. Allerdings stellen Symbole sicher, dass jeder Schlüssel einzigartig ist, auch wenn wir Symbole mit demselben Namen erstellen. Darüber hinaus werden Symbole nicht in Objekteigenschaftenaufzählungen angezeigt.
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
In diesem Beispiel ist der Schlüssel „hiddenKey“ eindeutig, und obwohl ein anderer Teil unseres Codes ein anderes Symbol („versteckt“) hätte erstellen können, wäre es völlig anders und hätte keinen Einfluss auf den in obj gespeicherten Wert.
Sie können Symbol sogar zusammen mit Object.defineProperty verwenden, um Objekten Eigenschaften auf kontrolliertere Weise hinzuzufügen und sicherzustellen, dass die Eigenschaften nicht aufzählbar sind.
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
In diesem Beispiel wird SecretKey nicht in der Schlüsselaufzählung des Objekts angezeigt, was es ideal für „private“ Werte macht, auf die nicht versehentlich zugegriffen oder die geändert werden sollten.
In JavaScript kann der Umgang mit großen Zahlen eine echte Herausforderung sein. Der Datentyp „Zahl“ hat eine Grenze für die genaue Darstellung von Ganzzahlen: Der größte sichere Ganzzahlwert ist 9007199254740991 (auch bekannt als Number.MAX_SAFE_INTEGER). Wenn Sie versuchen, mit größeren Zahlen zu arbeiten, kann es zu Präzisionsverlusten kommen, was zu Fehlern in Ihrer Anwendung führen kann.
Stellen Sie sich zum Beispiel vor, Sie erhalten eine große Zahl von einer externen API:
async function obtenerDatos() { try { const respuesta = await fetch('https://api.ejemplo.com/datos'); if (!respuesta.ok) { throw new Error('Error al obtener los datos'); } const datos = await respuesta.json(); console.log(datos); } catch (error) { console.error('Error:', error.message); } }
Wie Sie sehen, wird die Nummer 9007199254740999 fälschlicherweise in 9007199254741000 umgewandelt. Dies kann problematisch sein, wenn die Nummer für Ihre Anwendung von entscheidender Bedeutung ist, beispielsweise eine eindeutige Kennung oder ein finanzieller Betrag.
Wie vermeide ich dieses Problem?
Eine einfache und elegante Lösung ist die Verwendung des Datentyps BigInt, der in ECMAScript 2020 eingeführt wurde. BigInt kann viel größere Zahlen verarbeiten, ohne an Präzision zu verlieren. JSON verarbeitet BigInt jedoch nicht nativ, daher müssen Sie Zahlen beim Serialisieren in Zeichenfolgen konvertieren und sie dann beim Deserialisieren wieder zurückkonvertieren.
Hier ist ein Beispiel, wie Sie es tun könnten:
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Mit diesem Ansatz können Sie die Genauigkeit großer Zahlen aufrechterhalten, ohne wichtige Daten zu verlieren. Wenn Sie die Nummer erneut benötigen, konvertieren Sie sie einfach wieder in BigInt:
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
Wenn Sie nicht mit BigInt arbeiten möchten oder die Leistung ein Problem darstellt, besteht eine andere Strategie darin, große Zahlen einfach als Zeichenfolgen in JSON zu behandeln. Dies vermeidet das Präzisionsproblem auf Kosten der Konvertierungen in Ihrem Code.
Beispiel:
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Der richtige Umgang mit großen Zahlen ist nicht nur entscheidend für die Genauigkeit der Berechnungen, sondern auch für die Wahrung der Datenintegrität. Dies ist besonders wichtig, wenn Sie mit APIs oder Systemen von Drittanbietern arbeiten, die Sie nicht vollständig kontrollieren können. Eine falsch interpretierte Zahl könnte zu Fehlern in Ihrer Anwendung oder, schlimmer noch, zu Fehlern in Daten führen, die kritisch sein könnten, wie z. B. bei der Verarbeitung von Finanztransaktionen oder eindeutigen Identifikatoren in Datenbanken.
Denken Sie daran: Präzisionsgrenzen nicht ignorieren. Obwohl es wie ein kleines Detail erscheinen mag, ist es ein Bereich, in dem Anwendungen auf unerwartete und kostspielige Weise ausfallen können.
In JavaScript konvertieren if-Anweisungen Ausdrücke implizit in „wahre“ oder „falsche“ Werte, was zu unerwarteten Ergebnissen führen kann, wenn dieses Verhalten nicht berücksichtigt wird. Obwohl dieses Verhalten manchmal nützlich sein kann, wird empfohlen, es im Vergleich explizit anzugeben, um subtile Fehler zu vermeiden und die Lesbarkeit des Codes zu verbessern.
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Im obigen Beispiel wird die Bedingung nicht ausgeführt, da 0 als „falsch“ gilt. Dieses Verhalten kann jedoch bei der Arbeit mit komplexeren Werten schwer zu erkennen sein.
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
Tipp: Wann immer Sie es mit Werten zu tun haben, die falsch sein können, wie z. B. 0, null, falsch oder „“, ist es am besten, in Ihrem Vergleich explizit zu sein. Auf diese Weise stellen Sie sicher, dass die Logik gemäß Ihren Erwartungen ausgeführt wird und nicht aufgrund impliziten Typzwangsverhaltens.
Angenommen, Sie haben ein Objekt, das null sein kann, ein leeres Array [] oder ein leeres Objekt {}. Wenn Sie so etwas tun:
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Obwohl [] (ein leeres Array) ein gültiges und wahrheitsgemäßes Objekt ist, kann es in Zukunft zu Verwirrung führen, wenn Sie das Verhalten nicht vollständig verstehen. Anstatt sich auf impliziten Zwang zu verlassen, ist es am besten, explizitere Vergleiche anzustellen, wie zum Beispiel:
async function obtenerDatos() { try { const respuesta = await fetch('https://api.ejemplo.com/datos'); if (!respuesta.ok) { throw new Error('Error al obtener los datos'); } const datos = await respuesta.json(); console.log(datos); } catch (error) { console.error('Error:', error.message); } }
Durch die explizite Definition von Bedingungen verringern Sie das Risiko von Fehlern, die durch den automatischen Zwang von JavaScript verursacht werden. Dieser Ansatz macht Ihren Code klarer, lesbarer und vorhersehbarer. Darüber hinaus verbessert es die Wartbarkeit, da andere Personen (oder Sie selbst in Zukunft) die Logik schnell verstehen können, ohne sich an das implizite Verhalten falscher Werte in JavaScript erinnern zu müssen.
Eines der verwirrendsten Verhaltensweisen von JavaScript ist auf den nicht strikten Gleichheitsoperator (==) zurückzuführen. Dieser Operator führt eine sogenannte Typumwandlung durch, was bedeutet, dass er versucht, Werte in einen gemeinsamen Typ umzuwandeln, bevor er sie vergleicht. Dies kann zu überraschend unerwarteten und sehr schwer zu debuggenden Ergebnissen führen.
Zum Beispiel:
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
So etwas kann einen in der Entwicklung in den Wahnsinn treiben. Der ==-Operator vergleicht [] (ein leeres Array) mit ![] (was sich als falsch herausstellt, da [] als wahrer Wert betrachtet wird und ![] ihn in falsch umwandelt). Aufgrund der internen Zwangsregeln von JavaScript ist dies jedoch ein gültiges Ergebnis, auch wenn es auf den ersten Blick keinen Sinn ergibt.
JavaScript konvertiert beide Seiten des Vergleichs vor dem Vergleich in einen gemeinsamen Typ. In diesem Fall wird das leere Array [] im Vergleich zum booleschen Wert von ![] falsch. Diese Art von Zwang ist ein klares Beispiel dafür, wie subtile und schwer erkennbare Fehler auftreten können.
Um diese Probleme zu vermeiden, sollten Sie, wann immer möglich, strikte Gleichheit verwenden (===). Der Unterschied besteht darin, dass dieser -Operator keine Typerzwingung durchführt. Dies bedeutet, dass sowohl der Wert als auch der Typ der Variablen streng verglichen werden.
const productos = [ { nombre: 'Laptop', detalles: { precio: 1000 } }, { nombre: 'Teléfono', detalles: null }, { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } } ]; // Acceso seguro a la propiedad 'impuesto' de cada producto productos.forEach(producto => { const impuesto = producto?.detalles?.impuesto; console.log(impuesto); // undefined, null o el valor real });
Hier sind einige häufigere Beispiele dafür, wie nicht strikte Gleichheit (==) problematisch sein kann:
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Das obige ist der detaillierte Inhalt vonBest Practices in modernem JavaScript – Teil 2. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!