search
HomeWeb Front-endJS TutorialBest Practices in Modern JavaScript - Part 2

Mejores Prácticas en JavaScript Moderno - Parte 2

In the first part of this article, we explored the basics of modern JavaScript and some essential best practices to start writing cleaner, more efficient code. But as developers, we know that there is always more to learn and improve.

8. Optional chaining (?.)

When working with objects or nested structures, we sometimes face the need to check if a property exists before trying to access it. The optional chaining operator (?.) is a powerful tool that simplifies this task, avoiding property access errors of null or undefined values.

Why is it useful?

Imagine that you have a complex object structure and you are not sure if certain properties exist in it. Without optional chaining, you would have to do manual checks at each step, which can make your code longer and less readable. With the ?. operator, you can safely access properties and get undefined if any of the intermediate properties do not exist.

Basic example

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

In this case, since the product does not have the price property, the optional chaining returns undefined instead of generating an error.

Example with a more complex object

Imagine that you have a list of products with different properties, some of which may be empty or undefined:

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 this example, optional chaining allows us to avoid errors when trying to access product.details.tax, even if details is null or absent.

How does it improve your code?

  • Avoid access errors to null or undefined properties.
  • Simplifies the code, making security checks cleaner and more readable.
  • Allows you to work with uncertain or incomplete data, something very common when you work with responses from APIs or databases.

Bonus: Optional chaining with functions

Optional chaining can also be used with functions, which is very useful when you have functions that may not be defined on an object:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

Here, the getAge function is undefined (it's null), but it doesn't throw an error, it just returns undefined.

9. Use async/await for async handling

When you work with asynchronous operations in JavaScript, such as getting data from an API or reading files, the async/await syntax can be your best friend. Instead of using promises with .then() and .catch(), async/await allows you to write asynchronous code in a cleaner and more readable way, similar to how we would write synchronous code.

Why use async/await?

  • Simplicity and readability: You avoid "promise chains" that can become complicated to read and maintain.
  • More intuitive error handling: Using try/catch to handle errors is much clearer than using .catch().
  • More precise control: Allows await to be used anywhere in the function, making it easier to control more complex asynchronous flows.

Basic example of use:

Suppose we are working with an API that returns data. Using async/await instead of .then() makes the flow much easier to follow:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

Practical example: fetching data from an API and displaying it in the UI

Imagine that you have a web page where you need to display user information from an API. Here's an example of how you could do it using async/await to get the data and render it to the 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
});

Object.values()

Returns an array with all the values ​​of the properties of an object. Perfect when you just need the values ​​without the keys.

Example:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

Object.entries()

This is the most versatile method. Returns an array of arrays, where each sub-array contains a key and its corresponding value. This is useful if you want to work with both keys and values ​​in a single operation.

Example:

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);
  }
}

Bonus: Iteration with for...of

Did you know that you can combine these methods with for...of to make your code even cleaner? Here is an example using Object.entries():

Example:

// 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"]

This approach is cleaner and easier to read, especially if you are working with large or complex objects.

11. Use Map for non-primitive keys

When you need to associate values ​​with keys that are not strings or symbols, use Map. It is more robust and maintains the type and order of the keys.

Example:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

12. Use Symbol for unique keys

Symbols are a JavaScript feature that allows you to create unique and immutable keys, making them a powerful tool when we need to ensure that a value is not accidentally overwritten or accessed. Symbols cannot be accessed by methods like Object.keys(), for...in, or JSON.stringify(), making them perfect for private or "hidden" values.

Why use Symbol?

When we create properties of an object using keys such as text strings, they can be easily manipulated or overwritten. However, symbols ensure that each key is unique, even if we create symbols with the same name. Additionally, symbols will not appear in object property enumerations.

Basic example:

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 this example, the hiddenKey key is unique, and although another part of our code could have created another Symbol('hidden'), it would be completely different and would not affect the value stored in obj.

Advanced Example: Combining Symbol with Object.defineProperty

You can even use Symbol together with Object.defineProperty to add properties to objects in a more controlled way, ensuring that the properties are non-enumerable.

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

In this example, secretKey will not appear in the object's key enumeration, making it ideal for "private" values ​​that should not be accessed or modified by accident.

Considerations:

  • Symbols are useful for avoiding property name conflicts, especially when working with third-party libraries or APIs.
  • Although symbols are not strictly "private", the fact that they are not conventionally accessible helps protect the integrity of the data.
  • Please note that symbols cannot be serialized to JSON, so if you need to transmit data, be sure to handle the Symbol properties appropriately.

13. Be careful with JSON and large numbers

In JavaScript, handling large numbers can be a real challenge. The Number data type has a limit on representing integers accurately: the largest safe integer value is 9007199254740991 (also known as Number.MAX_SAFE_INTEGER). If you try to work with numbers larger than this, you may lose precision, which could cause errors in your application.

For example, imagine you receive a large number from an external 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);
  }
}

As you see, the number 9007199254740999 is incorrectly converted to 9007199254741000. This can be problematic if the number is critical to your application, such as a unique identifier or a financial amount.

How to avoid this problem?

A simple and elegant solution is to use the BigInt data type, introduced in ECMAScript 2020. BigInt can handle much larger numbers without losing precision. However, JSON doesn't natively handle BigInt, so you'll need to convert numbers to strings when serializing them and then convert them back when you deserialize them.

Here is an example of how you could do it:

Solution with BigInt and JSON.stringify

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

By using this approach, you can maintain the accuracy of large numbers without losing important data. When you need the number again, just convert it back to 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
});

Other strategies

If you don't want to work with BigInt or if performance is a concern, another strategy is to simply treat large numbers as strings in JSON. This avoids the precision problem at the cost of having to do conversions in your code.

Example:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

Why is it important?

Proper handling of large numbers is not only crucial for the accuracy of the calculations, but also for maintaining data integrity. This is especially important when you work with third-party APIs or systems that you don't fully control. A misinterpreted number could lead to failures in your application, or worse, errors in data that could be critical, such as the handling of financial transactions or unique identifiers in databases.

Remember: don't ignore precision limits. Although it may seem like a small detail, it is an area where applications can fail in unexpected and costly ways.

14. Handle expressions in if statements explicitly

In JavaScript, if statements implicitly convert expressions to "truthy" or "falsy" values, which can lead to unexpected results if this behavior is not taken into account. Although this behavior can be useful at times, it is recommended to be explicit in the comparison to avoid subtle errors and improve code readability.

What does "truthy" or "falsy" mean?

  • "Falsy" refers to values ​​that are considered equivalent to false when evaluated in a conditional expression. Examples: 0, "" (empty string), null, undefined, NaN.
  • "Truthy" are all values ​​that are not falsy, that is, any value that is not one of the above. Example: any number other than 0, any non-empty string, objects, etc.

Implicit example (may give unexpected results)

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

In the example above, the condition is not executed, since 0 is considered "falsy". However, this behavior can be difficult to detect when working with more complex values.

Explicit example (better for readability)

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
});

Tip: Whenever you are dealing with values ​​that may be false, such as 0, null, false, or "", it is best to be explicit in your comparison. This way you ensure that the logic is executed according to your expectations and not because of implicit type coercion behavior.

Another example with ambiguous values

Let's consider that you have an object that can be null, an empty array [], or an empty object {}. If you do something like this:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

Although [] (an empty array) is a valid and truthful object, it can lead to confusion in the future if you don't fully understand the behavior. Instead of relying on implicit coercion, it is best to make more explicit comparisons, such as:

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);
  }
}

Why is it important?

By defining conditions explicitly, you reduce the risk of errors caused by JavaScript's automatic coercion. This approach makes your code clearer, more readable, and more predictable. Additionally, it improves maintainability, as other people (or yourself in the future) will be able to quickly understand the logic without having to remember the implicit behavior of falsy values ​​in JavaScript.

15. Use strict equality (===) whenever possible

One of the most confusing behaviors of JavaScript comes from the non-strict equality operator (==). This operator performs what is known as type coercion, which means that it attempts to convert values ​​to a common type before comparing them. This can produce results surprisingly unexpected and very difficult to debug.

For example:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined

This is the kind of thing that can drive you crazy when you're developing. The == operator compares [] (an empty array) with ![] (which turns out to be false, since [] is considered a true value and ![] converts it to false). However, by JavaScript's internal coercion rules, this is a valid result, although it doesn't make sense at first glance.

Why is this happening?

JavaScript converts both sides of the comparison to a common type before comparing them. In this case, the empty array [] becomes false when compared to the boolean value of ![]. This type of coercion is a clear example of how subtle and difficult to identify errors can occur.

Tip: Always use strict equality

To avoid these problems, whenever possible, you should use strict equality (===). The difference is that this operator does not perform type coercion . This means that it compares both the value and type of the variables strictly.

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
});

More typical examples

Here are some more common examples of how non-strict equality (==) can be problematic:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined

Why is it important to use ===?

  • Prediction and reliability: Using === gives you more predictable comparisons, without surprises or type conversions.
  • Avoid hard-to-detect bugs: When your code starts to get larger and more complex, bugs related to type coercion can be very difficult to find and debug.
  • Improve code readability: It's easier for other developers (or yourself in the future) to understand your code when you see explicit comparisons, without the confusion of implicit conversions.

The above is the detailed content of Best Practices in Modern JavaScript - Part 2. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
JavaScript Comments: A Guide to Using // and /* */JavaScript Comments: A Guide to Using // and /* */May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

JavaScript Frameworks: Powering Modern Web DevelopmentJavaScript Frameworks: Powering Modern Web DevelopmentMay 02, 2025 am 12:04 AM

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools