Saltar al contenido principal

9 publicaciones etiquetados con "ES2019"

Ver Todas las Etiquetas

Subsume JSON también conocido como JSON ⊂ ECMAScript

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

Con la propuesta JSON ⊂ ECMAScript, JSON se convierte en un subconjunto sintáctico de ECMAScript. Si te sorprende que esto no fuera ya el caso, no estás solo.

El comportamiento anterior en ES2018

En ES2018, los literales de cadenas de ECMAScript no podían contener caracteres U+2028 LINE SEPARATOR y U+2029 PARAGRAPH SEPARATOR sin escapar, porque se consideran terminadores de línea incluso en ese contexto:

// Una cadena que contiene un carácter U+2028 sin procesar.
const LS = '
';
// → ES2018: SyntaxError

// Una cadena que contiene un carácter U+2029 sin procesar, producido por `eval`:
const PS = eval('"\u2029"');
// → ES2018: SyntaxError

Esto es problemático porque las cadenas JSON pueden contener estos caracteres. Como resultado, los desarrolladores tenían que implementar lógica de post-procesamiento especializada al incrustar JSON válido en programas ECMAScript para manejar estos caracteres. Sin dicha lógica, el código tendría errores sutiles o incluso problemas de seguridad.

Array.prototype.sort` estable

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

Supongamos que tienes un array de perros, donde cada perro tiene un nombre y una calificación. (Si esto suena a un ejemplo extraño, debes saber que hay una cuenta de Twitter que se especializa exactamente en esto… ¡No preguntes!)

// Nota cómo el array está preordenado alfabéticamente por `name`.
const doggos = [
{ name: 'Abby', rating: 12 },
{ name: 'Bandit', rating: 13 },
{ name: 'Choco', rating: 14 },
{ name: 'Daisy', rating: 12 },
{ name: 'Elmo', rating: 12 },
{ name: 'Falco', rating: 13 },
{ name: 'Ghost', rating: 14 },
];
// Ordena los perros por `rating` en orden descendente.
// (Esto actualiza `doggos` directamente).
doggos.sort((a, b) => b.rating - a.rating);

`Symbol.prototype.description`

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

Los Symbols de JavaScript pueden tener una descripción al momento de su creación:

const symbol = Symbol('foo');
// ^^^^^

Anteriormente, la única forma de acceder a esta descripción programáticamente era indirectamente a través de Symbol.prototype.toString():

const symbol = Symbol('foo');
// ^^^^^
symbol.toString();
// → 'Symbol(foo)'
// ^^^
symbol.toString().slice(7, -1); // 🤔
// → 'foo'

Sin embargo, el código es un tanto mágico, no muy autoexplicativo, y viola el principio de “expresar intención, no implementación”. La técnica mencionada tampoco permite distinguir entre un símbolo sin descripción (es decir, Symbol()) y un símbolo cuya descripción es la cadena vacía (es decir, Symbol('')).

`Object.fromEntries`

· 4 min de lectura
Mathias Bynens ([@mathias](https://twitter.com/mathias)), susurrador de JavaScript

Object.fromEntries es una adición útil a la biblioteca incorporada de JavaScript. Antes de explicar lo que hace, es útil entender la API Object.entries ya existente.

Object.entries

La API Object.entries ha existido durante un tiempo.

Para cada par clave-valor en un objeto, Object.entries te da un array donde el primer elemento es la clave y el segundo elemento es el valor.

Object.entries es especialmente útil en combinación con for-of, ya que permite iterar elegantemente sobre todos los pares clave-valor en un objeto:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

for (const [key, value] of entries) {
console.log(`El valor de ${key} es ${value}.`);
}
// Registros:
// El valor de x es 42.
// El valor de y es 50.

Desafortunadamente, no hay una forma fácil de volver del resultado de entries a un objeto equivalente... ¡hasta ahora!

Object.fromEntries

La nueva API Object.fromEntries realiza la inversa de Object.entries. Esto hace que sea fácil reconstruir un objeto basado en sus entradas:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

const result = Object.fromEntries(entries);
// → { x: 42, y: 50 }

Un caso de uso común es transformar objetos. Ahora puedes hacerlo iterando sobre sus entradas y luego usando métodos de arrays con los que ya puedas estar familiarizado:

const object = { x: 42, y: 50, abc: 9001 };
const result = Object.fromEntries(
Object.entries(object)
.filter(([ key, value ]) => key.length === 1)
.map(([ key, value ]) => [ key, value * 2 ])
);
// → { x: 84, y: 100 }

En este ejemplo, usamos filter para obtener solo las claves de longitud 1, es decir, solo las claves x y y, pero no la clave abc. Luego usamos map sobre las entradas restantes y devolvemos un par clave-valor actualizado por cada una. En este ejemplo, duplicamos cada valor multiplicándolo por 2. El resultado final es un nuevo objeto con solo las propiedades x y y, y los nuevos valores.

`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}

`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):

Binding opcional en `catch`

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

La cláusula catch de las sentencias try solía requerir un binding:

try {
doSomethingThatMightThrow();
} catch (exception) {
// ^^^^^^^^^
// ¡Debemos nombrar el binding, incluso si no lo usamos!
handleException();
}

En ES2019, ahora se puede usar catch sin un binding. Esto es útil si no necesitas el objeto exception en el código que maneja la excepción.

try {
doSomethingThatMightThrow();
} catch { // → ¡Sin binding!
handleException();
}

Soporte para binding opcional en catch

`String.prototype.trimStart` y `String.prototype.trimEnd`

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

ES2019 introduce String.prototype.trimStart() y String.prototype.trimEnd():

const string = '  hola mundo  ';
string.trimStart();
// → 'hola mundo '
string.trimEnd();
// → ' hola mundo'
string.trim(); // ES5
// → 'hola mundo'

Esta funcionalidad estaba previamente disponible a través de los métodos no estándares trimLeft() y trimRight(), que permanecen como alias de los nuevos métodos por compatibilidad hacia atrás.

const string = '  hola mundo  ';
string.trimStart();
// → 'hola mundo '
string.trimLeft();
// → 'hola mundo '
string.trimEnd();
// → ' hola mundo'
string.trimRight();
// → ' hola mundo'
string.trim(); // ES5
// → 'hola mundo'