Skip to content
Aprende Angular de forma rápida y efectiva  Ver curso

Actualizaciones de Javascript – ES2018

Desde 2015 con la publicación del estándar ES6, Javascript ha recibido actualizaciones a un ritmo vertiginoso. ¿El resultado? JS es ahora uno de los lenguajes de programación más modernos y versátiles.

Las prácticas arrow functions, las técnicas de destructuring, o los operadores async / await son algunas de las novedades que se incorporaron hasta 2017.

Javascript ES2018

En este artículo voy a detallarte las novedades más interesantes de Javascript, incorporadas en 2018.

1 – Asignación por destructuring en Objetos

ES6 incorporaba el spread operator y los parámetros rest para hacer asignaciones por destructuring con Arrays.

Esto permitía 2 cosas:

  • Asignar un subarray de elementos a una única variable
  • Y descomponer un array en valores individuales.

    Funcionaba así:

// Rest elements for array destructuring assignment:
const primes = [2, 3, 5, 7, 11];
const [first, second, ...rest] = primes;
console.log(first); // 2
console.log(second); // 3
console.log(rest); // [5, 7, 11]

// Spread elements for array literals:
const primes2 = [first, second, ...rest];
console.log(primes2); // [2, 3, 5, 7, 11]

Pues bien, desde 2018, se pueden aplicar los mismos operadores de forma análoga a los objetos. Así:

// Rest properties for object destructuring assignment:
const person = {
    firstName: 'Peter',
    lastName: 'Parker',
    age: 26,
} 
const { age, ...name } = person;
console.log(age); // 26
console.log(name); // {firstName: 'Peter', lastName: 'Parker'}

// Spread properties for object literals:
const person2 = { age, ...name };
console.log(person2);
// {age: 26, firstName: "Peter", lastName: "Parker"}

¿Y de qué sirve esto?
Aquí tienes algunas situaciones en las que te va a ser útil:

  • Clonación de objetos:
    Es una forma bastante más simple de clonar objetos planos que su alternativa (Object.assign({})).
    Ejemplo:
// Shallow-clone an object:
const data = { x: 42, y: 27, label: 'Treasure' };
// Antes:
const clone1 = Object.assign({}, data);
// Ahora:
const clone2 = { ...data };
  • Merge de objetos:
    Del mismo modo, te facilita la fusión entre 2 objetos
    Ejemplo:
// Merge two objects:
const defaultSettings = { logWarnings: false, logErrors: false };
const userSettings = { logErrors: true };

// Antes
const settings1 = Object.assign({}, defaultSettings, userSettings);

// Ahora
const settings2 = { ...defaultSettings, ...userSettings };

// En ambos casos el resultado es
// { logWarnings: false, logErrors: true }
  • Deshacerte de parte de un objeto:
    A veces necesitas una versión «reducida» de un objeto, porque no te interesa exponer alguna propiedad.

Esto es extremadamente simple ahora:

const person = {
    name: 'Peter',
    age: 26,
    gender: 'Male',
    email: 'private@email.com',
    address: 'private address 25, 08180, Somewhere.'
} 
const { email, address, ...simplePerson } = person;

console.log(simplePerson); //{name: "Peter", age: 26, gender: "Male"}

2 – finally en Promises

Otra incorporación de ES6 fueron las Promises: Un mecanismo para ejecutar tareas asíncronas, y llamar una función de callback en caso de éxito (resolve) o error (reject).

Pues bien, desde 2018 las Promises te permiten llamar a una función de callback al completarse (independientemente del resultado). A continuación te dejo un ejemplo claro de uso:

const fetchAndDisplay = ({ url, element }) => {
  showLoadingSpinner();
  fetch(url)
    .then((response) => response.text())
    .then((text) => {
       element.textContent = text;
    })
    .catch((error) => {
       element.textContent = error.message;    
    })
    .finally(() => {
       hideLoadingSpinner();
    });
};

3 – Iteradores asíncronos

Un iterador es un contenedor de elementos que se puede recorrer sin conocer su arquitectura, solo llamando a su método next().

En Javascript, existían los iteradores síncronos, donde este método devolvía dos valores:

  • value con el elemento actual del contenedor
  • y done indicando si el iterador ha finalizado o no.

Supongamos un iterador que contiene el array [1,2,3]. Obtendríamos sus valores así:

syncIterator.next();
//{value:1, done:false} 
syncIterator.next();
//{value:2, done:false} 
syncIterator.next();
//{value:3, done:false} 
syncIterator.next();
//{value:undefined, done:true} 

Además, puedes usar for..of para iterarlo (devuelve directamente el valor de cada iteración y finaliza internamente cuando done es true):

for (let value of syncIterator) {
    console.log(value);
} // output: 1, 2, 3

Desde 2018, Javascript acepta también iteradores que devuelven valores asíncronos. Cada llamada a next, en este caso, lo que devuelve es una Promise, así que para capturar el siguiente valor de la iteración, lo harías así:

asyncIterator.next().then(({ value, done }) => /* ...do something with value and done... */);

Buclando sobre Iteradores asíncronos

Junto con los iteradores asíncronos, se ha incorporado también la sintaxis for-await-of para recorrerlos.
Imagina un iterador que lee un archivo (de forma asíncrona como es habitual) línea a línea. Podríamos recorrer y printar todas las líneas, así:

for await (const line of readLines(filePath)) {
  console.log(line);
}

4 – Mejoras en las expresiones regulares

Se han añadido varias mejoras al sistema de expresiones regulares de Javascript. Entre otras cosas…

Named capture groups

Ahora se pueden identificar grupos de captura a través de nombres, lo que facilita su lectura. Por ejemplo:

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';

Lookbehind assertions

Hasta el momento, las expresiones regulares de JS tenían un mecanismo para comprobar si una expresión iba seguida de un determinado patrón (lookahead: ?=pattern).

Por ejemplo, la siguiente expresión : /^([0-9]{2})(?=H)/ daría positivo para números de 2 cifras seguidos de la letra H (sin incluirla en el match).

const regex = /^([0-9]{2})(?=H)/;
regex.exec('12H');
// encuentra 12 como match.

Lo que no había es un mecanismo para comprobar si la expresión estaba precedida de un determinado patrón. Esto es lo que llamamos lookbehind (?<=pattern). Para comprobar si una cantidad monetaria esta precedida por el símbolo del €, podríamos hacerlo así:

const regex = /(?<=€)([0-9])+/;
regex.test('€2000');
// encuentra 2000 como coincidencia

Reflexiones personales

Como ves, JS no para de evolucionar. Cada año se incorporan novedades para facilitar el trabajo de los desarrolladores y adaptar el lenguaje a las necesidades que se detectan. En próximos posts te contaré las novedades que se han añadido este año 2019, y lo que se espera para 2020.

¿Te ha gustado este artículo? No te cortes, déjame un comentario y ayúdame a compartirlo 😉

Published inJavascript

7 Comments

  1. jolugama jolugama

    Los Named capture groups los desconocía al completo y me parecen super útiles. Gracias

  2. Santi García Llorente Santi García Llorente

    Buen resumen, Enrique. Deseando escuchar las novedades de JS para 2020

  3. Oduber Vasquez Brito Oduber Vasquez Brito

    excelente muchas gracias!

  4. Carla Carla

    Muchas gracias Enrique! Muy buen artículo

  5. BRUNO BARANGE BRUNO BARANGE

    Muy bueno, gracias por compartir 🙂

  6. Jerson Morocho Jerson Morocho

    Muy buena la parte desctructuring, ahora los objetos seran más faciles de manipulas

  7. Carlos Carlos

    Excelente artículo amigo, gracias por compartir tus conocimientos

Deja un comentario