Saltar al contenido principal

Combinadores de Promesas

· 5 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Desde la introducción de las promesas en ES2015, JavaScript ha soportado exactamente dos combinadores de promesas: los métodos estáticos Promise.all y Promise.race.

Actualmente, dos nuevas propuestas están atravesando el proceso de estandarización: Promise.allSettled, y Promise.any. Con estas adiciones, habrá un total de cuatro combinadores de promesas en JavaScript, cada uno permitiendo diferentes casos de uso.

`Array.prototype.flat` y `Array.prototype.flatMap`

· 2 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Array.prototype.flat

El arreglo en este ejemplo tiene varios niveles de profundidad: contiene un arreglo que a su vez contiene otro arreglo.

const array = [1, [2, [3]]];
// ^^^^^^^^^^^^^ arreglo exterior
// ^^^^^^^^ arreglo interior
// ^^^ arreglo más interior

Array#flat devuelve una versión aplanda de un arreglo dado.

array.flat();
// → [1, 2, [3]]

// …es equivalente a:
array.flat(1);
// → [1, 2, [3]]

La profundidad predeterminada es 1, pero puedes pasar cualquier número para aplanar recursivamente hasta esa profundidad. Para seguir aplanando recursivamente hasta que el resultado no contenga más arreglos anidados, pasamos Infinity.

// Aplanar recursivamente hasta que el arreglo no contenga más arreglos anidados:
array.flat(Infinity);
// → [1, 2, 3]

¿Por qué este método se llama Array.prototype.flat y no Array.prototype.flatten? ¡Lee nuestro artículo #SmooshGate para descubrirlo!

Array.prototype.flatMap

Aquí hay otro ejemplo. Tenemos una función duplicate que toma un valor y devuelve un arreglo que contiene ese valor dos veces. Si aplicamos duplicate a cada valor en un arreglo, terminamos con un arreglo anidado.

const duplicate = (x) => [x, x];

[2, 3, 4].map(duplicate);
// → [[2, 2], [3, 3], [4, 4]]

Entonces puedes llamar a flat sobre el resultado para aplanar el arreglo:

[2, 3, 4].map(duplicate).flat(); // 🐌
// → [2, 2, 3, 3, 4, 4]

Dado que este patrón es tan común en la programación funcional, ahora hay un método dedicado llamado flatMap para ello.

[2, 3, 4].flatMap(duplicate); // 🚀
// → [2, 2, 3, 3, 4, 4]

flatMap es un poco más eficiente en comparación con realizar un map seguido de un flat por separado.

¿Interesado en casos de uso de flatMap? Consulta la explicación de Axel Rauschmayer.

Compatibilidad con Array#{flat,flatMap}

Separadores numéricos

· 2 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Los literales numéricos grandes son difíciles de interpretar rápidamente para el ojo humano, especialmente cuando hay muchos dígitos repetidos:

1000000000000
1019436871.42

Para mejorar la legibilidad, una nueva característica del lenguaje JavaScript permite guiones bajos como separadores en literales numéricos. Por lo tanto, lo anterior ahora puede reescribirse para agrupar los dígitos por miles, por ejemplo:

`String.prototype.matchAll`

· 3 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Es común aplicar repetidamente la misma expresión regular en una cadena para obtener todas las coincidencias. Hasta cierto punto, esto ya es posible hoy en día utilizando el método String#match.

En este ejemplo, encontramos todas las palabras que consisten únicamente en dígitos hexadecimales y luego registramos cada coincidencia:

const string = 'Números hex mágicos: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.match(regex)) {
console.log(match);
}

// Salida:
//
// 'DEADBEEF'
// 'CAFE'

Sin embargo, esto solo te da las subcadenas que coinciden. Normalmente, no solo quieres las subcadenas, también deseas información adicional como el índice de cada subcadena o los grupos de captura dentro de cada coincidencia.

Ya es posible lograr esto escribiendo tu propio bucle y haciendo un seguimiento de los objetos de coincidencia tú mismo, pero es un poco tedioso y no muy conveniente:

const string = 'Números hex mágicos: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
let match;
while (match = regex.exec(string)) {
console.log(match);
}

// Salida:
//
// [ 'DEADBEEF', índice: 19, entrada: 'Números hex mágicos: DEADBEEF CAFE' ]
// [ 'CAFE', índice: 28, entrada: 'Números hex mágicos: DEADBEEF CAFE' ]

La nueva API String#matchAll lo hace más fácil que nunca: ahora puedes escribir un simple bucle for-of para obtener todos los objetos de coincidencia.

const string = 'Números hex mágicos: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.matchAll(regex)) {
console.log(match);
}

// Salida:
//
// [ 'DEADBEEF', índice: 19, entrada: 'Números hex mágicos: DEADBEEF CAFE' ]
// [ 'CAFE', índice: 28, entrada: 'Números hex mágicos: DEADBEEF CAFE' ]

String#matchAll es especialmente útil para expresiones regulares con grupos de captura. Te proporciona toda la información de cada coincidencia individual, incluidos los grupos de captura.

const string = 'Repositorios favoritos de GitHub: tc39/ecma262 v8/v8.dev';
const regex = /\b(?<owner>[a-z0-9]+)\/(?<repo>[a-z0-9\.]+)\b/g;
for (const match of string.matchAll(regex)) {
console.log(`${match[0]} en ${match.index} con '${match.input}'`);
console.log(`→ owner: ${match.groups.owner}`);
console.log(`→ repo: ${match.groups.repo}`);
}

`Intl.ListFormat`

· 4 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias)) y Frank Yung-Fong Tang

Las aplicaciones web modernas suelen usar listas que consisten en datos dinámicos. Por ejemplo, una aplicación de visualización de fotos podría mostrar algo como:

Esta foto incluye Ada, Edith, y Grace.

Un juego basado en texto podría tener un tipo diferente de lista:

Elige tu superpoder: invisibilidad, psicokinesis, o empatía.

Como cada idioma tiene diferentes convenciones y palabras para el formato de listas, implementar un formateador de listas localizado no es trivial. Esto no solo requiere una lista de todas las palabras (como “y” u “o” en los ejemplos anteriores) para cada idioma que se quiera soportar, sino que también es necesario codificar las convenciones de formato exactas para todos esos idiomas. El CLDR de Unicode proporciona estos datos, pero para usarlos en JavaScript, deben estar integrados y enviados junto con el código de otras bibliotecas. Esto desafortunadamente aumenta el tamaño del paquete de dichas bibliotecas, lo que impacta negativamente los tiempos de carga, los costos de parseo/compilación y el consumo de memoria.

Exportación de nombres de espacios en módulos

· Lectura de un minuto
Mathias Bynens ([@mathias](https://twitter.com/mathias))

En módulos de JavaScript, ya era posible usar la siguiente sintaxis:

import * as utils from './utils.mjs';

Sin embargo, no existía una sintaxis de export simétrica… hasta ahora:

export * as utils from './utils.mjs';

Esto es equivalente a lo siguiente:

import * as utils from './utils.mjs';
export { utils };

Campos de clase públicos y privados

· 5 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Varias propuestas amplían la sintaxis existente de clases en JavaScript con nuevas funcionalidades. Este artículo explica la nueva sintaxis de campos de clase públicos en V8 v7.2 y Chrome 72, así como la próxima sintaxis de campos de clase privados.

Aquí hay un ejemplo de código que crea una instancia de una clase llamada IncreasingCounter:

const counter = new IncreasingCounter();
counter.value;
// registros '¡Obteniendo el valor actual!'
// → 0
counter.increment();
counter.value;
// registros '¡Obteniendo el valor actual!'
// → 1

Nota que acceder a value ejecuta algún código (es decir, registra un mensaje) antes de devolver el resultado. Ahora pregúntate, ¿cómo implementarías esta clase en JavaScript? 🤔

Sintaxis de clases de ES2015

Aquí se muestra cómo IncreasingCounter podría implementarse utilizando la sintaxis de clases de ES2015:

class IncreasingCounter {
constructor() {
this._count = 0;
}
get value() {
console.log('¡Obteniendo el valor actual!');
return this._count;
}
increment() {
this._count++;
}
}

La clase instala el getter value y un método increment en el prototipo. Más interesante aún, la clase tiene un constructor que crea una propiedad de instancia _count y establece su valor predeterminado en 0. Actualmente, tendemos a usar el prefijo de guion bajo para denotar que _count no debería ser utilizado directamente por los consumidores de la clase, pero eso es solo una convención; no es realmente una propiedad "privada" con semántica especial aplicada por el lenguaje.

`Intl.RelativeTimeFormat`

· 5 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Las aplicaciones web modernas suelen usar frases como “ayer”, “hace 42 segundos” o “en 3 meses” en lugar de fechas completas y marcas de tiempo. Estos valores formateados en tiempo relativo se han vuelto tan comunes que varias bibliotecas populares implementan funciones utilitarias que los formatean de manera localizada. (Ejemplos incluyen Moment.js, Globalize, y date-fns.)

`JSON.stringify` bien formado

· Lectura de un minuto
Mathias Bynens ([@mathias](https://twitter.com/mathias))

JSON.stringify anteriormente estaba especificado para devolver cadenas Unicode mal formadas si la entrada contenía algún sustituto solitario:

JSON.stringify('\uD800');
// → '"�"'

La propuesta de “JSON.stringify bien formado” cambia JSON.stringify para que produzca secuencias de escape para sustitutos solitarios, haciendo que su salida sea Unicode válido (y representable en UTF-8):

Módulos de JavaScript

· 22 min de lectura
Addy Osmani ([@addyosmani](https://twitter.com/addyosmani)) y Mathias Bynens ([@mathias](https://twitter.com/mathias))

¡Los módulos de JavaScript ahora son compatibles con todos los navegadores principales!

Este artículo explica cómo usar módulos de JS, cómo implementarlos de manera responsable, y cómo el equipo de Chrome está trabajando para hacer que los módulos sean aún mejores en el futuro.

¿Qué son los módulos de JS?

Los módulos de JS (también conocidos como “módulos de ES” o “módulos ECMAScript”) son una característica nueva importante, o más bien una colección de nuevas características. Es posible que hayas usado un sistema de módulos de JavaScript en el pasado. Tal vez usaste CommonJS como en Node.js, o tal vez AMD, o quizás algo más. Todos estos sistemas de módulos tienen algo en común: te permiten importar y exportar cosas.