Pular para o conteúdo principal

`await` de nível superior

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

await de nível superior permite que os desenvolvedores usem a palavra-chave await fora de funções assíncronas. Ele age como uma grande função assíncrona, fazendo com que outros módulos que o importam esperem antes de começar a avaliar seu corpo.

Coalescência nula

· Leitura de 7 minutos
Justin Ridgewell

A proposta de coalescência nula (??) adiciona um novo operador de curto-circuito destinado a lidar com valores padrão.

Você pode já estar familiarizado com os outros operadores de curto-circuito && e ||. Ambos lidam com valores “truthy” e “falsy”. Imagine o exemplo de código lhs && rhs. Se lhs (lido como, lado esquerdo) for falsy, a expressão avalia para lhs. Caso contrário, avalia para rhs (lido como, lado direito). O oposto é verdadeiro para o exemplo de código lhs || rhs. Se lhs for truthy, a expressão avalia para lhs. Caso contrário, avalia para rhs.

Encadeamento opcional

· Leitura de 5 minutos
Maya Armyanova ([@Zmayski](https://twitter.com/Zmayski)), destruidora de cadeias opcionais

Cadeias longas de acessos a propriedades em JavaScript podem ser propensas a erros, já que qualquer uma delas pode ser avaliada como null ou undefined (também conhecidos como valores “nulos”). Verificar a existência de propriedade em cada etapa facilmente se transforma em uma estrutura profundamente aninhada de instruções if ou uma condição if longa que replica a cadeia de acesso à propriedade:

Subsume JSON ou seja, JSON ⊂ ECMAScript

· Leitura de 6 minutos
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Com a proposta JSON ⊂ ECMAScript, JSON torna-se um subconjunto sintático do ECMAScript. Se você está surpreso por isso ainda não ser o caso, você não está sozinho!

O comportamento do ES2018 antigo

Em ES2018, literais string do ECMAScript não podiam conter os caracteres U+2028 LINE SEPARATOR e U+2029 PARAGRAPH SEPARATOR sem escapá-los, porque eles são considerados terminadores de linhas mesmo nesse contexto:

// Uma string contendo um caractere bruto U+2028.
const LS = '
';
// → ES2018: SyntaxError

// Uma string contendo um caractere bruto U+2029, produzida por `eval`:
const PS = eval('"\u2029"');
// → ES2018: SyntaxError

Isso é problemático porque strings JSON podem conter esses caracteres. Como resultado, os desenvolvedores tinham que implementar lógica de pós-processamento especializada ao incorporar JSON válido em programas ECMAScript para lidar com esses caracteres. Sem essa lógica, o código teria bugs sutis ou até mesmo problemas de segurança!

`Intl.NumberFormat`

· Leitura de 4 minutos
Mathias Bynens ([@mathias](https://twitter.com/mathias)) e Shane F. Carr

Você pode já estar familiarizado com a API Intl.NumberFormat, já que tem sido suportada em ambientes modernos há algum tempo.

Na sua forma mais básica, Intl.NumberFormat permite criar uma instância de formatador reutilizável que suporta formatação de números sensível ao local. Assim como outras APIs Intl.*Format, uma instância de formatador suporta tanto o método format quanto o método formatToParts:

`globalThis`

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

Se você já escreveu JavaScript para uso em um navegador web antes, pode ter usado window para acessar o this global. No Node.js, você pode ter usado global. Se você escreveu um código que deve funcionar em qualquer um dos ambientes, pode ter detectado qual deles está disponível e usado isso - mas a lista de identificadores a verificar cresce com o número de ambientes e casos de uso que você deseja suportar. Isso foge do controle rapidamente:

Referências fracas e finalizadores

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

Geralmente, referências a objetos são fortemente mantidas no JavaScript, o que significa que enquanto você tiver uma referência ao objeto, ele não será coletado pelo garbage collector.

const ref = { x: 42, y: 51 };
// Enquanto você tiver acesso a `ref` (ou qualquer outra referência ao
// mesmo objeto), o objeto não será coletado pelo garbage collector.

Atualmente, WeakMaps e WeakSets são a única maneira de referenciar um objeto de forma quase fraca no JavaScript: adicionar um objeto como chave a um WeakMap ou WeakSet não impede que ele seja coletado pelo garbage collector.

const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// Não temos mais uma referência a `ref` neste escopo de bloco, então ele
// pode ser coletado pelo garbage collector agora, mesmo que seja uma chave no `wm`
// ao qual ainda temos acesso.

Ordenação estável de `Array.prototype.sort`

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

Digamos que você tenha um array de cachorros, onde cada cachorro tem um nome e uma classificação. (Se isso parecer um exemplo estranho, você deve saber que existe uma conta no Twitter que se especializa exatamente nisso... Não pergunte!)

// Note como o array já está ordenado alfabeticamente por `nome`.
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 },
];
// Ordene os cachorros por `rating` em ordem decrescente.
// (Isso atualiza `doggos` diretamente.)
doggos.sort((a, b) => b.rating - a.rating);

`Symbol.prototype.description`

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

Os Symbols do JavaScript podem receber uma descrição ao serem criados:

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

Anteriormente, a única maneira de acessar essa descrição de forma programática era indiretamente através de Symbol.prototype.toString():

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

No entanto, o código parece um pouco mágico, não é muito autoexplicativo, e viola o princípio "exprima a intenção, não a implementação". A técnica acima também não permite distinguir entre um símbolo sem descrição (ou seja, Symbol()) e um símbolo com uma string vazia como descrição (ou seja, Symbol('')).

`Object.fromEntries`

· Leitura de 4 minutos
Mathias Bynens ([@mathias](https://twitter.com/mathias)), encantador de JavaScript

Object.fromEntries é uma adição útil à biblioteca JavaScript incorporada. Antes de explicar o que ele faz, é útil entender a API pré-existente Object.entries.

Object.entries

A API Object.entries existe há algum tempo.

Para cada par de chave-valor em um objeto, Object.entries fornece um array em que o primeiro elemento é a chave e o segundo elemento é o valor.

Object.entries é especialmente útil em combinação com for-of, pois permite iterar de forma muito elegante sobre todos os pares de chave-valor em um objeto:

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

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

Infelizmente, não há uma maneira fácil de voltar do resultado de entries para um objeto equivalente… até agora!

Object.fromEntries

A nova API Object.fromEntries realiza a operação inversa de Object.entries. Isso facilita a reconstrução de um objeto com base em seus entries:

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

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

Um caso de uso comum é a transformação de objetos. Agora você pode fazer isso iterando sobre seus entries e usando métodos de array com os quais você já pode 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 }

Neste exemplo, estamos filterando o objeto para obter apenas chaves de comprimento 1, ou seja, apenas as chaves x e y, mas não a chave abc. Em seguida, mapeamos os entries restantes e retornamos um par atualizado de chave-valor para cada um. Neste exemplo, dobramos cada valor multiplicando-o por 2. O resultado final é um novo objeto, com apenas as propriedades x e y, e os novos valores.