Pular para o conteúdo principal

9 postagens marcadas com "ES2019"

Ver todas os Marcadores

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!

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.

`Array.prototype.flat` e `Array.prototype.flatMap`

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

Array.prototype.flat

O array neste exemplo tem vários níveis de profundidade: contém um array que, por sua vez, contém outro array.

const array = [1, [2, [3]]];
// ^^^^^^^^^^^^^ array externo
// ^^^^^^^^ array interno
// ^^^ array mais interno

Array#flat retorna uma versão achatada de um array fornecido.

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

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

A profundidade padrão é 1, mas você pode passar qualquer número para achatar recursivamente até essa profundidade. Para continuar achatando recursivamente até o resultado não conter mais arrays aninhados, passamos Infinity.

// Achatar recursivamente até o array não conter mais arrays aninhados:
array.flat(Infinity);
// → [1, 2, 3]

Por que esse método é chamado de Array.prototype.flat e não Array.prototype.flatten? Leia nosso artigo sobre #SmooshGate para descobrir!

Array.prototype.flatMap

Aqui está outro exemplo. Temos uma função duplicate que recebe um valor e retorna um array que contém esse valor duas vezes. Se aplicarmos duplicate a cada valor de um array, terminamos com um array aninhado.

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

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

Você pode então chamar flat no resultado para achatar o array:

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

Como esse padrão é tão comum na programação funcional, agora há um método dedicado flatMap para ele.

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

flatMap é um pouco mais eficiente em comparação a fazer um map seguido de um flat separadamente.

Interessado em casos de uso para flatMap? Confira a explicação de Axel Rauschmayer.

Suporte a Array#{flat,flatMap}

`JSON.stringify` Bem-formado

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

JSON.stringify anteriormente era especificado para retornar strings Unicode malformadas se a entrada contivesse algum surrogate solitário:

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

A proposta “JSON.stringify Bem-formado” altera JSON.stringify para que ele gere sequências de escape para surrogates solitários, tornando sua saída Unicode válido (e representável em UTF-8):

Vínculo opcional de `catch`

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

A cláusula catch de instruções try costumava exigir um vínculo:

try {
doSomethingThatMightThrow();
} catch (exception) {
// ^^^^^^^^^
// Precisamos nomear o vínculo, mesmo que não o utilizemos!
handleException();
}

No ES2019, catch agora pode ser usado sem um vínculo. Isso é útil se você não precisar do objeto exception no código que lida com a exceção.

try {
doSomethingThatMightThrow();
} catch { // → Sem vínculo!
handleException();
}

Suporte ao vínculo opcional catch

`String.prototype.trimStart` e `String.prototype.trimEnd`

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

ES2019 introduz String.prototype.trimStart() e String.prototype.trimEnd():

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

Essa funcionalidade estava anteriormente disponível através dos métodos não padronizados trimLeft() e trimRight(), que permanecem como aliases dos novos métodos para compatibilidade retroativa.

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