Dans la première partie de cet article, nous avons exploré les bases du JavaScript moderne et quelques bonnes pratiques essentielles pour commencer à écrire du code plus propre et plus efficace. Mais en tant que développeurs, nous savons qu'il y a toujours plus à apprendre et à améliorer.
Lorsque nous travaillons avec des objets ou des structures imbriquées, nous sommes parfois confrontés au besoin de vérifier si une propriété existe avant d'essayer d'y accéder. L'opérateur de chaînage facultatif (?.) est un outil puissant qui simplifie cette tâche, en évitant les erreurs d'accès aux propriétés de valeurs nulles ou non définies.
Imaginez que vous avez une structure d'objet complexe et que vous ne savez pas si certaines propriétés y existent. Sans chaînage facultatif, vous devrez effectuer des vérifications manuelles à chaque étape, ce qui peut rendre votre code plus long et moins lisible. Avec l'opérateur ?., vous pouvez accéder en toute sécurité aux propriétés et devenir indéfini si l'une des propriétés intermédiaires n'existe pas.
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Dans ce cas, puisque le produit n'a pas la propriété price, le chaînage optionnel renvoie undefined au lieu de générer une erreur.
Imaginez que vous ayez une liste de produits avec des propriétés différentes, dont certaines peuvent être vides ou indéfinies :
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 });
Dans cet exemple, le chaînage facultatif nous permet d'éviter les erreurs lors de la tentative d'accès à product.details.tax, même si les détails sont nuls ou absents.
Le chaînage optionnel peut également être utilisé avec des fonctions, ce qui est très utile lorsque vous avez des fonctions qui ne peuvent pas être définies sur un objet :
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Ici, la fonction getAge n'est pas définie (elle est nulle), mais elle ne génère pas d'erreur, elle renvoie simplement undéfini.
Lorsque vous travaillez avec des opérations asynchrones en JavaScript, telles que l'obtention de données à partir d'une API ou la lecture de fichiers, la syntaxe async/await peut être votre meilleure amie. Au lieu d'utiliser des promesses avec .then() et .catch(), async/await vous permet d'écrire du code asynchrone d'une manière plus propre et plus lisible, de la même manière que nous écrivions du code synchrone.
Supposons que nous travaillions avec une API qui renvoie des données. Utiliser async/await au lieu de .then() rend le flux beaucoup plus facile à suivre :
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Imaginez que vous ayez une page Web sur laquelle vous devez afficher des informations utilisateur à partir d'une API. Voici un exemple de la façon dont vous pouvez le faire en utilisant async/await pour obtenir les données et les restituer à l'interface :
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 });
Renvoie un tableau avec toutes les valeurs des propriétés d'un objet. Parfait quand on a juste besoin des valeurs sans les clés.
Exemple :
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
C'est la méthode la plus polyvalente. Renvoie un tableau de tableaux, où chaque sous-tableau contient une clé et sa valeur correspondante. Ceci est utile si vous souhaitez travailler à la fois avec des clés et des valeurs en une seule opération.
Exemple :
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); } }
Saviez-vous que vous pouvez combiner ces méthodes avec for...of pour rendre votre code encore plus propre ? Voici un exemple utilisant Object.entries() :
Exemple :
// 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"]
Cette approche est plus claire et plus facile à lire, surtout si vous travaillez avec des objets volumineux ou complexes.
Lorsque vous devez associer des valeurs à des clés qui ne sont pas des chaînes ou des symboles, utilisez Map. Il est plus robuste et conserve le type et l'ordre des clés.
Exemple :
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Les symboles sont une fonctionnalité JavaScript qui vous permet de créer des clés uniques et immuables, ce qui en fait un outil puissant lorsque nous devons nous assurer qu'une valeur n'est pas écrasée ou consultée accidentellement. Les symboles ne sont pas accessibles par des méthodes telles que Object.keys(), for...in ou JSON.stringify(), ce qui les rend parfaits pour les valeurs privées ou "cachées".
Lorsque nous créons les propriétés d'un objet à l'aide de clés telles que des chaînes de texte, elles peuvent être facilement manipulées ou écrasées. Cependant, les symboles garantissent que chaque clé est unique, même si nous créons des symboles portant le même nom. De plus, les symboles n'apparaîtront pas dans les énumérations de propriétés d'objet.
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 });
Dans cet exemple, la clé HiddenKey est unique, et bien qu'une autre partie de notre code aurait pu créer un autre Symbol('hidden'), elle serait complètement différente et n'affecterait pas la valeur stockée dans obj.
Vous pouvez même utiliser Symbol avec Object.defineProperty pour ajouter des propriétés aux objets de manière plus contrôlée, en garantissant que les propriétés ne sont pas énumérables.
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Dans cet exemple, secretKey n'apparaîtra pas dans l'énumération des clés de l'objet, ce qui le rend idéal pour les valeurs « privées » auxquelles il ne faut pas accéder ou modifier par accident.
En JavaScript, gérer de grands nombres peut être un véritable défi. Le type de données Number a une limite quant à la représentation précise des entiers : la plus grande valeur entière sûre est 9007199254740991 (également connue sous le nom de Number.MAX_SAFE_INTEGER). Si vous essayez de travailler avec des nombres supérieurs à cela, vous risquez de perdre en précision, ce qui pourrait provoquer des erreurs dans votre application.
Par exemple, imaginez que vous recevez un grand nombre d'une API externe :
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); } }
Comme vous le voyez, le numéro 9007199254740999 est incorrectement converti en 9007199254741000. Cela peut être problématique si le numéro est essentiel à votre candidature, comme un identifiant unique ou un montant financier.
Comment éviter ce problème ?
Une solution simple et élégante consiste à utiliser le type de données BigInt, introduit dans ECMAScript 2020. BigInt peut gérer des nombres beaucoup plus grands sans perdre en précision. Cependant, JSON ne gère pas nativement BigInt, vous devrez donc convertir les nombres en chaînes lors de leur sérialisation, puis les reconvertir lorsque vous les désérialisez.
Voici un exemple de la façon dont vous pourriez procéder :
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
En utilisant cette approche, vous pouvez maintenir l'exactitude de grands nombres sans perdre de données importantes. Lorsque vous aurez à nouveau besoin du numéro, reconvertissez-le simplement en 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 });
Si vous ne souhaitez pas travailler avec BigInt ou si les performances sont un problème, une autre stratégie consiste simplement à traiter les grands nombres comme des chaînes en JSON. Cela évite le problème de précision au prix de devoir effectuer des conversions dans votre code.
Exemple :
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Une bonne gestion des grands nombres est non seulement cruciale pour l'exactitude des calculs, mais également pour maintenir l'intégrité des données. Ceci est particulièrement important lorsque vous travaillez avec des API ou des systèmes tiers que vous ne contrôlez pas entièrement. Un numéro mal interprété pourrait entraîner des échecs dans votre application, ou pire, des erreurs dans des données qui pourraient être critiques, comme le traitement des transactions financières ou des identifiants uniques dans les bases de données.
Rappelez-vous : n'ignorez pas les limites de précision. Même si cela peut sembler un petit détail, il s'agit d'un domaine dans lequel les applications peuvent échouer de manière inattendue et coûteuse.
En JavaScript, les instructions if convertissent implicitement les expressions en valeurs « vraies » ou « fausses », ce qui peut conduire à des résultats inattendus si ce comportement n'est pas pris en compte. Bien que ce comportement puisse parfois être utile, il est recommandé d'être explicite dans la comparaison pour éviter des erreurs subtiles et améliorer la lisibilité du code.
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
Dans l'exemple ci-dessus, la condition n'est pas exécutée, puisque 0 est considéré comme "faux". Cependant, ce comportement peut être difficile à détecter lorsque vous travaillez avec des valeurs plus complexes.
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 });
Astuce : Chaque fois que vous avez affaire à des valeurs qui peuvent être fausses, telles que 0, null, false ou "", il est préférable d'être explicite dans votre comparaison. De cette façon, vous vous assurez que la logique est exécutée conformément à vos attentes et non à cause d'un comportement de coercition de type implicite.
Considérons que vous avez un objet qui peut être nul, un tableau vide [] ou un objet vide {}. Si vous faites quelque chose comme ça :
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Bien que [] (un tableau vide) soit un objet valide et véridique, cela peut prêter à confusion à l'avenir si vous ne comprenez pas complètement le comportement. Au lieu de s'appuyer sur une coercition implicite, il est préférable de faire des comparaisons plus explicites, telles que :
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); } }
En définissant explicitement les conditions, vous réduisez le risque d'erreurs causées par la coercition automatique de JavaScript. Cette approche rend votre code plus clair, plus lisible et plus prévisible. De plus, cela améliore la maintenabilité, car d'autres personnes (ou vous-même à l'avenir) seront capables de comprendre rapidement la logique sans avoir à se souvenir du comportement implicite des fausses valeurs en JavaScript.
L'un des comportements les plus déroutants de JavaScript vient de l'opérateur d'égalité non strict (==). Cet opérateur effectue ce que l'on appelle une coercition de type, ce qui signifie qu'il tente de convertir les valeurs en un type commun avant de les comparer. Cela peut produire des résultats étonnamment inattendus et très difficiles à déboguer.
Par exemple :
const producto = {}; const impuesto = producto?.precio?.impuesto; console.log(impuesto); // undefined
C'est le genre de chose qui peut vous rendre fou lorsque vous vous développez. L'opérateur == compare [] (un tableau vide) avec ![] (ce qui s'avère faux, puisque [] est considéré comme une valeur vraie et ![] la convertit en faux). Cependant, selon les règles de coercition internes de JavaScript, il s'agit d'un résultat valide, même s'il n'a pas de sens à première vue.
JavaScript convertit les deux côtés de la comparaison en un type commun avant de les comparer. Dans ce cas, le tableau vide [] devient faux par rapport à la valeur booléenne de ![]. Ce type de coercition est un exemple clair de la façon dont des erreurs subtiles et difficiles à identifier peuvent survenir.
Pour éviter ces problèmes, dans la mesure du possible, vous devez utiliser l'égalité stricte (===). La différence est que cet opérateur n'effectue pas de coercition de type . Cela signifie qu'il compare strictement la valeur et le type des variables.
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 });
Voici quelques exemples plus courants de la façon dont l'égalité non stricte (==) peut être problématique :
const usuario = { nombre: 'Juan', obtenerEdad: null }; const edad = usuario.obtenerEdad?.(); console.log(edad); // undefined
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!