ES2020: Novedades de JavaScript en 2020

ES2020

ES2020: Novedades de JavaScript en 2020

Este es el segundo de una serie de artículos donde vamos a repasar las novedades de los últimos años en JavaScript. En el anterior artículo ya vimos las novedades de JavaScript en 2021, en este artículo cogeremos el DeLorean para viajar un año en el pasado y repasar las novedades de JavaScript en 2020, es decir, las novedades de ES2020.

Al igual que en el anterior artículo, me voy a centrar exclusivamente en aquellas novedades de ES2020 que sean más asequibles. Las novedades que impliquen un uso avanzado del lenguaje las comentaré simplemente de pasada.

String.prototype.matchAll

Este nuevo método de las cadenas de texto, nos permite comprobar si dicha cadena de texto concuerda con una expresión regular, cosa que ya hacia el método match(), pero en este caso nos indica las diferentes coincidencias que encuentra.

Como de costumbre, lo mejor es ver un ejemplo:

var re = /\d/g; // expresión regular para buscar un número
var str = "El primer número es 5 y el segundo 8";
var iterator = str.matchAll(re);
for (var match of iterator) { console.log(match); }

import()

Sirve para importar módulos de forma dinámica (bajo demanda), ya que la implementación convencional es estática y el modulo se importa si o si, mientras que de este modo podemos condicionar su carga si hace falta.

Tenemos que esta expresión (aunque lo parezca no es una función o método) indicando como parámetro la URL del módulo que queremos cargar, y nos devolverá una promesa.

if (condicion) {
  import(url)
    .then(module => { 
      module.ejemploDeFuncionExportada();
      module.default(); 
    })
    .catch(err => { 
      document.write(err.message); 
    });
}

Si dicha promesa se resuleve satisfactoriamente, tendremos un objeto (module) con todos los exports de dicho módulo. Si queremos acceder a una función exportada por defecto, podemos usar module.default(); en lugar de indicar su nombre.

Como son promesas, podemos usar async/await para simplificar el código.

  async function ejemplo() { // función asíncrona!
    try {
      var module = await import(url);
      module.ejemploDeFuncionExportada();
      module.default();
    } catch(err) {
      document.write(err.message);        
    }   
  }
  if (condicion) { ejemplo(); }

NOTA: A diferencia del import «normal», con este import() dinámico se pueden cargar también scripts convencionales.

BigInt

Un nuevo tipo de dato que soporta números enteros superiores a 253 que es el máximo que soporta el tipo de dato Number (osea, el valor de Number.MAX_SAFE_INTEGER, que concretamente es 9007199254740991).

Se puede crear simplemente añadiendo una «n» al final del numero o bien usando el constructor BigInt()

var x = 1n; // ejemplo de un bigint

Solo es recomendable usarlos si tenemos realmente la necesidad de hacerlo, y como es muy raro que tengáis ese necesidad, no vamos a entrar en detalle.

Promise.allSettled()

Es un método estático de la clase Promise, muy similar al método estático all() de dicha clase.

La diferencia es que este método solo termina cuando todas las promesas han sido procesadas (es decir, no queda ninguna pendiente) independientemente de que hayan sido aceptadas o rechazadas. Cosa que no sucede con el método all(), que termina si se produce cualquier rechazo o error.

Por lo demás, el método allSettled() funciona exactamente igual que el método all(), así que, para más detalles sobre su uso os recomiendo el artículo que hice sobre promesas en JavaScript donde se explican las promesas y este método estático.

globalThis

En el navegador Web el objeto global es window, en Node.js es global y en un WebWorker es self.

Para evitar líos tenemos globalThis, que equivale a cualquiera de los 3 según donde se ejecute el código.

Esto facilita la portabilidad del código de un entorno a otro.

for-in mechanics

Los bucle for-in sirven para recorrerse las propiedades de un objeto, y la especificación original indicaba que el orden en el que recorrian dichos atributos era arbitrario.

var objeto = { a: 1, b: 2 }
for (atributo in objeto) { console.log(atributo, " = ", objeto[atributo]); }

Aunque los motores de los navegadores solían ser consistentes en dicho orden, ahora la especificación determina un orden concreto para evitar problemas, como por ejemplo, los derivados de añadir o eliminar propiedades durante el bucle.

Optional Chaining

En mi opinión, de las novedades más interesantes de ES2020.

Se trata de un nuevo operador ?. (interrogante + punto) para acceder a propiedades de objetos.

Cuando intentamos acceder a la propiedad de un objeto que no existe, recibimos un bonito error. Con el optional chaining, podemos recibir un undefined en su lugar. Es sobretodo útil para acceder a estructuras de tipo árbol sin miedo a que se encuentren incompletas.

Su uso es muy sencillo:

var padre = { hijo : { nieto : {} } };
console.log(padre.hijo.nieto.bisnieto.tataranieto); // esto da error, porque intentamos accecer a una propiedad de un objeto (bisnieto) que no existe
console.log(padre.hijo.nieto.bisnieto?.tataranieto); // esto NO da error, simplemente devuelve un undefined porque bisnieto no existe (y por lo tanto sus propiedades tampoco)

Como podéis ver es tan sencillo como colocar un ? al final de la propiedad que nos interesa que no de error si no existe.

Veamos otro ejemplo:

console.log(document.querySelector("#patata")?.innerText); // no da error aunque no encuentre el elemento!

Tambien sirve para funciones y arrays:

window.pintar(100, 200); // el método pintar no existe en window, da error
window.pintar?.(100, 200); // no da error
window.coches[0]; // window no tiene un array llamado coches, da error
window.coches?.[0]; // no da error.

Seguro que habéis tenido este tipo de problema más de una vez, ¿a que si?

Tenéis más información en la MDN.

Nullish Coalescing Operator

Otra novedad muy interesante de ES2020. De nuevo se trata de otro operador, esta vez es el operador ?? (dos interrogantes) que funciona con dos operandos. Comprueba si el primer operando es null o undefined, y en caso afirmativo, la expresión devuelve el segundo operando.

var a = null;
var b = "hola";
var c = false;
console.log(a ?? b); // a ?? b devuelve el valor de "b", ya que "a" vale null/undefined
console.log(c ?? b); // c ?? b devuelve el valor de "c", ya que "c" NO vale null/undefined

Es algo bastante útil para definir valores por defecto:

function saluda(nombre) {
  alert("Hola " + (nombre ?? "Alumno"));
}
saluda();
saluda("Pepe");

import.meta

Y terminamos el repaso a las novedades de ES2020, con otra novedad relacionada con los módulos.

En este caso se trata de una propiedad que almacena información sobre el módulo que puede resultarnos útil, como por ejemplo, la URL de dicho módulo. Y en dicha URL se incluyen posibles parámetros que le podamos haber indicando, por lo que es una forma de poder pasarle diferentes parámetros a un módulo al importarlo.

Por ejemplo, imaginemos el siguiente módulo llamado saluda.js

export default function saluda() {
	// mostramos la URL en la consola
	console.log(import.meta.url);
	// pillamos los datos de la URL
	var params = new URL(import.meta.url).searchParams;
	alert(params.get('nombre') + " " + params.get('apellido'));	
}

Después, podemos usar dicho módulo de este modo:

import saluda from './saluda.js?nombre=Abel&apellido=Camarena';
saluda();

Escribe un comentario