Saltar al contenido principal

`await` de nivel superior

· 5 min de lectura
Myles Borins ([@MylesBorins](https://twitter.com/MylesBorins))

await de nivel superior permite a los desarrolladores usar la palabra clave await fuera de las funciones async. Actúa como una gran función async que hace que otros módulos que los import esperen antes de comenzar a evaluar su contenido.

Coalescencia nula

· 7 min de lectura
Justin Ridgewell

La propuesta de coalescencia nula (??) agrega un nuevo operador de cortocircuito destinado a manejar valores predeterminados.

Probablemente ya estés familiarizado con los otros operadores de cortocircuito && y ||. Ambos operadores manejan valores “truthy” y “falsy”. Imagina el ejemplo de código lhs && rhs. Si lhs (lado izquierdo) es falsy, la expresión se evalúa como lhs. De lo contrario, se evalúa como rhs (lado derecho). Lo opuesto ocurre con el ejemplo de código lhs || rhs. Si lhs es truthy, la expresión se evalúa como lhs. De lo contrario, se evalúa como rhs.

Encadenamiento opcional

· 5 min de lectura
Maya Armyanova ([@Zmayski](https://twitter.com/Zmayski)), rompedora de cadenas opcionales

Las cadenas largas de accesos a propiedades en JavaScript pueden ser propensas a errores, ya que cualquiera de ellas podría evaluarse como null o undefined (también conocidos como valores “nulos”). Verificar la existencia de propiedades en cada paso fácilmente se convierte en una estructura profundamente anidada de sentencias if o en una larga condición if que replica la cadena de acceso a propiedades:

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.

`Intl.NumberFormat`

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

Es posible que ya estés familiarizado con la API Intl.NumberFormat, ya que ha sido compatible con varios entornos modernos durante algún tiempo.

En su forma más básica, Intl.NumberFormat te permite crear una instancia de formato reutilizable que admite el formato de números adaptado al idioma. Al igual que otras APIs de Intl.*Format, una instancia de formateador admite ambos métodos: format y formatToParts:

`globalThis`

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

Si has escrito JavaScript para usar en un navegador web antes, es posible que hayas usado window para acceder al this global. En Node.js, quizás hayas usado global. Si has escrito código que debe funcionar en cualquiera de estos entornos, quizás detectaste cuál de estos está disponible y luego lo usaste, pero la lista de identificadores a verificar crece con el número de entornos y casos de uso que deseas admitir. Esto se sale de control rápidamente:

Referencias débiles y finalizadores

· 11 min de lectura
Sathya Gunasekaran ([@_gsathya](https://twitter.com/_gsathya)), Mathias Bynens ([@mathias](https://twitter.com/mathias)), Shu-yu Guo ([@_shu](https://twitter.com/_shu)), y Leszek Swirski ([@leszekswirski](https://twitter.com/leszekswirski))

Generalmente, las referencias a los objetos se mantienen fuertemente en JavaScript, lo que significa que mientras tengas una referencia al objeto, no será recolectado por el recolector de basura.

const ref = { x: 42, y: 51 };
// Mientras tengas acceso a `ref` (o cualquier otra referencia al
// mismo objeto), el objeto no será recolectado por el recolector de basura.

Actualmente, WeakMaps y WeakSets son la única forma de referenciar de manera virtualmente débil un objeto en JavaScript: agregar un objeto como una clave a un WeakMap o WeakSet no impide que sea recolectado por el recolector de basura.

const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// Ya no tenemos una referencia a `ref` en este alcance de bloque, así que
// puede ser recolectado por el recolector de basura ahora, incluso aunque sea una clave en `wm` a
// la cual todavía tenemos acceso.

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.