Hoje estamos publicando a segunda parte da tradução de inovações em JavaScript. Aqui falamos sobre separadores de dígitos de números, sobre números BigInt, sobre como trabalhar com matrizes e objetos, sobre 
globalThis , sobre classificação, sobre a API de internacionalização e sobre promessas.

→ 
A primeira parteSeparadores de números
Números longos encontrados nos programas são difíceis de ler. Por exemplo, 
1000000000 é um bilhão em decimal. Mas de relance é difícil de entender. Portanto, se o leitor do programa encontrar algo semelhante - ele, para percebê-lo corretamente, terá que considerar cuidadosamente zeros.
No JavaScript moderno, você pode usar o separador de dígitos dos números - um sublinhado ( 
_ ), cujo uso melhora a legibilidade de números longos. Veja como os números escritos usando um delimitador aparecem no código:
 var billion = 1_000_000_000; console.log( billion );  
Separadores podem ser usados para dividir arbitrariamente números em fragmentos. JavaScript, ao lidar com números, simplesmente ignora separadores. Eles podem ser usados ao escrever qualquer número: números inteiros, ponto flutuante, binário, hexadecimal, octal.
 console.log( 1_000_000_000.11 );  
→ Suporte
- TC39: Etapa 3
- Chrome: mais de 75
- Nó: 12,5+
Tipo de dados Bigint
Os números em JavaScript são criados usando a função construtora 
Number .
O valor máximo que pode ser representado com segurança usando o tipo de dados 
Number é (2⁵³ - 1), ou seja, 9007199254740991. Esse número pode ser visto usando a construção 
Number.MAX_SAFE_INTEGER .
Observe que, quando um literal numérico é usado no código JS, o JavaScript o processa, criando um objeto baseado nele, usando o construtor 
Number . O protótipo deste objeto contém métodos para trabalhar com números. Isso acontece com todos 
os tipos de dados primitivos .
O que acontecerá se tentarmos adicionar algo ao número 9007199254740991?
 console.log( Number.MAX_SAFE_INTEGER );  
O resultado da adição de 
Number.MAX_SAFE_INTEGER e 10, a segunda saída do 
console.log() , está incorreto. Isso ocorre porque o JS não pode executar corretamente cálculos com números maiores que o valor de 
Number.MAX_SAFE_INTEGER . Você pode lidar com esse problema usando o 
bigint dados 
bigint .
O tipo 
bigint permite representar números inteiros maiores que 
Number.MAX_SAFE_INTEGER . Trabalhar com valores BigInt é semelhante a trabalhar com valores do tipo 
Number . Em particular, o idioma possui a função 
BigInt() , com a qual você pode criar os valores correspondentes, e o tipo de dados 
bigint primitivo 
bigint usado para representar números inteiros grandes.
 var large = BigInt( 9007199254740991 ); console.log( large );  
O JavaScript adiciona 
n ao final dos literais do BigInt. Para nós, isso significa que esses literais podem ser escritos adicionando 
n ao final dos números inteiros.
Agora que temos os números BigInt à nossa disposição, podemos realizar operações matemáticas com segurança em grandes números do tipo 
bigint .
 var large = 9007199254740991n; console.log( large + 10n );  
Um número de número de tipo não é igual a um número de tipo 
bigint . Em particular, estamos falando do fato de que os números BigInt podem ser apenas números inteiros. Como resultado, verifica-se que você não pode executar operações aritméticas que usam os tipos 
bigint e 
number .
Note-se que a função 
BigInt() pode assumir vários números: decimal, binário, hexadecimal, octal. Dentro desta função, eles serão convertidos em números, para a representação da qual o sistema de números decimais é usado.
O tipo 
bigint também suporta separadores de bits:
 var large = 9_007_199_254_741_001n; console.log( large );  
→ Suporte
- TC39: Etapa 3
- Chrome: mais de 67
- Nó: 10.4+
- Firefox: 68+
Novos métodos de matriz: .flat () e .flatMap ()
Aqui, falaremos sobre os novos métodos de protótipo para o objeto 
Array - os 
.flat() e 
.flatMap() .
▍ método .flat ()
Agora, os objetos do tipo 
Array têm um novo método - 
.flat(n) . Ele retorna uma nova matriz, permitindo elevar recursivamente os elementos das matrizes para o nível especificado 
n . Por padrão, 
n é 1. Esse método pode transmitir 
n igual a 
Infinity , o que permite converter uma matriz com matrizes aninhadas em uma matriz unidimensional.
 var nums = [1, [2, [3, [4, 5]]]]; console.log( nums.flat() );  
→ Suporte
- TC39: Etapa 4
- Chrome: mais de 69
- Nó: 11+
- Firefox: 62+
▍ método .flatMap ()
Ao resolver tarefas diárias, o programador às vezes pode precisar processar a matriz usando o método 
.map() com sua subsequente transformação em uma estrutura plana. Por exemplo, crie uma matriz contendo os números e quadrados desses números:
 var nums = [1, 2, 3]; var squares = nums.map( n => [ n, n*n ] ) console.log( squares );  
A solução para esse problema pode ser simplificada usando o método 
.flatMap() . Ele converte as matrizes retornadas pela função de retorno de chamada passada para ele, assim como eles converteriam seu método 
.flat() com o parâmetro 
n igual a 1.
 var nums = [1, 2, 3]; var makeSquare = n => [ n, n*n ]; console.log( nums.flatMap( makeSquare ) );  
→ Suporte
- TC39: Etapa 4
- Chrome: mais de 69
- Nó: 11+
- Firefox: 62+
Método Object.fromEntries ()
É possível extrair pares de tipos de chaves de um objeto 
: pode ser usado usando o 
Object Method estático, que retorna uma matriz, cada elemento da qual é uma matriz contendo, como o primeiro elemento, uma chave e como o segundo - um valor.
 var obj = { x: 1, y: 2, z: 3 }; var objEntries = Object.entries( obj ); console.log( objEntries );  
Agora temos à nossa disposição um método estático 
Object.fromEntries() , que nos permite converter uma estrutura semelhante novamente em um objeto.
 var entries = [["x", 1],["y", 2],["z", 3]]; var obj = Object.fromEntries( entries ); console.log( obj );  
O método 
entries() foi usado para facilitar a filtragem e o mapeamento dos dados armazenados nos objetos. O resultado é uma matriz. Mas, até agora, a tarefa de converter essa matriz em um objeto não teve uma solução bonita. É para resolver esse problema que você pode usar o método 
Object.fromEntries() .
 var obj = { x: 1, y: 2, z: 3 };  
Se a estrutura 
Map : data for usada para armazenar a 
: pairs 
: os dados nela serão armazenados na ordem em que foram adicionados a ela. Ao mesmo tempo, como os dados são armazenados se assemelha à matriz retornada pelo método 
Object.entries() . O método 
Object.fromEntries() é fácil de usar para transformar estruturas de dados do 
Map em objetos.
 var m = new Map([["x", 1],["y", 2],["z", 3]]); console.log( m );  
→ Suporte
- TC39: Etapa 4
- Chrome: mais de 73
- Nó: 12+
- Firefox: 63+
▍ Propriedade global globalThis
Estamos familiarizados com a 
this usada no JavaScript. Não possui algum valor fixo. Em vez disso, o significado 
this depende do contexto em que é acessado. Em qualquer ambiente, a 
this aponta para um objeto global quando é acessado a partir do contexto do nível mais alto. Este é o significado global 
this .
No JavaScript baseado em navegador, por exemplo, o valor global para 
this é o objeto de 
window . Você pode verificar isso usando a construção 
console.log(this) no nível superior do arquivo JavaScript (no contexto mais externo) ou no console JS do navegador.
Acessando isso no console do navegadorO valor global 
this no Node.js aponta para um objeto 
global . Dentro de um trabalhador da Web, ele aponta para o próprio trabalhador. No entanto, obter 
this valor global não é uma tarefa fácil. O fato é que você não pode se referir a 
this nenhum lugar. Por exemplo, se você tentar fazer isso no construtor da classe, isso indica que 
this aponta para uma instância da classe correspondente.
Em alguns ambientes, a 
this self pode ser usada para acessar o valor global 
this . Essa palavra-chave desempenha o mesmo papel que os mecanismos para acessar esse valor nos navegadores, no Node.js e nos trabalhadores da Web. Usando o conhecimento de como o valor global 
this é chamado em ambientes diferentes, você pode criar uma função que retorne esse valor:
 const getGlobalThis = () => { if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global !== 'undefined') return global; if (typeof this !== 'undefined') return this; throw new Error('Unable to locate global `this`'); }; var globalThis = getGlobalThis(); 
Diante de nós, há um polyfill primitivo para obter 
this objeto global. Leia mais sobre isso 
aqui . O JavaScript agora possui a palavra-chave 
globalThis . Ele fornece uma maneira universal de acessar o valor global 
this para diferentes ambientes e não depende da localização do programa a partir do qual é acessado.
 var obj = { fn: function() {  console.log( 'this', this === obj );  
→ Suporte
- TC39: Etapa 3
- Chrome: mais de 71
- Nó: 12+
- Firefox: 65+
Classificação estável
O padrão ECMAScript não oferece um algoritmo de classificação de matriz específico que os mecanismos JavaScript devem implementar. Ele descreve apenas a API usada para classificação. Como resultado, usando diferentes mecanismos JS, é possível encontrar diferenças no desempenho das operações de classificação e na estabilidade (estabilidade) dos algoritmos de classificação.
Agora, o padrão 
exige que as matrizes de classificação sejam estáveis. Detalhes sobre a estabilidade da classificação podem ser encontrados 
aqui . A essência dessa característica dos algoritmos de classificação é a seguinte. O algoritmo é estável se o resultado da classificação, que é uma matriz modificada, contiver elementos com os mesmos valores que não foram afetados pela classificação na mesma ordem em que foram colocados na matriz original. Considere um exemplo:
 var list = [  { name: 'Anna', age: 21 },  { name: 'Barbra', age: 25 },  { name: 'Zoe', age: 18 },  { name: 'Natasha', age: 25 } ];  
Aqui, a matriz da 
list contém os objetos é classificada pelo campo de 
age desses objetos. Na matriz da 
list , um objeto com a propriedade 
name igual a 
Barbra está localizado antes do objeto com a propriedade 
name igual a 
Natasha . Como os valores de 
age desses objetos são iguais, poderíamos esperar que na matriz classificada esses elementos retenham a ordem de arranjo anterior em relação um ao outro. No entanto, na prática, isso não poderia ser esperado. Como exatamente a matriz classificada será formada dependia inteiramente do mecanismo JS usado.
Agora, todos os navegadores modernos e o Node.js usam um algoritmo de classificação estável, chamado ao acessar o método da matriz 
.sort() . Isso permite obter sempre, para os mesmos dados, o mesmo resultado:
 
No passado, alguns mecanismos JS suportavam classificação estável, mas apenas para pequenas matrizes. Para melhorar o desempenho ao processar matrizes grandes, eles poderiam usar algoritmos mais rápidos e sacrificar a estabilidade da classificação.
→ Suporte
- Chrome: mais de 70
- Nó: 12+
- Firefox: 62+
API de internacionalização
A API de internacionalização destina-se a organizar comparações de cadeias, para formatar números, datas e horas, como é habitual em vários padrões regionais (localidades). O acesso a essa API é organizado por meio 
do objeto Intl . Este objeto fornece construtores para criar objetos classificadores e objetos que formatam dados. A lista de códigos de idioma suportados pelo objeto 
Intl pode ser encontrada 
aqui .
▍Intl.RelativeTimeFormat ()
Em muitas aplicações, muitas vezes é necessário imprimir a hora em um formato relativo. Pode parecer "5 minutos atrás", "ontem", "1 minuto atrás" e assim por diante. Se os materiais do site forem traduzidos para diferentes idiomas, você deverá incluir todas as combinações possíveis de construções relativas que descrevem o horário na montagem do site.
O JS agora possui 
o Intl.RelativeTimeFormat(locale, config) , que permite criar sistemas de formatação de data e hora para vários 
Intl.RelativeTimeFormat(locale, config) . Em particular, estamos falando de objetos que possuem um 
método .format(value, unit) , que permite gerar vários registros de data e hora relativos. É assim:
 
→ Suporte
- TC39: Etapa 3
- Chrome: mais de 71
- Nó: 12+
- Firefox: 65+
▍Intl.ListFormat ()
O construtor 
Intl.ListFormat permite combinar itens de lista usando as palavras 
and ( 
) e 
or ( 
). Ao criar o objeto correspondente, o construtor recebe o código do idioma e o objeto com os parâmetros. Seu parâmetro de 
type pode ser 
conjunction , 
disjunction e 
unit . Por exemplo, se queremos combinar os elementos da 
[apples, mangoes, bananas] usando um objeto de conjunção, obtemos uma sequência da forma 
apples, mangoes and bananas . Se usarmos um objeto de disjunção, obteremos uma série de 
apples, mangoes or bananas .
O objeto criado pelo 
construtor Intl.ListFormat possui 
um método Intl.ListFormat .format(list) que combina listas. Considere um exemplo:
 
→ Suporte
▍Intl.Locale ()
O conceito de "padrão regional" é geralmente muito mais do que apenas o nome de um idioma. Isso pode incluir o tipo de calendário, informações sobre os ciclos de tempo usados e os nomes dos idiomas. 
O construtor Intl.Locale(localeId, config) usado para criar cadeias de caracteres de 
Intl.Locale(localeId, config) formatadas com base no objeto de 
config passado para ele.
Intl.Locale objeto criado usando o 
Intl.Locale contém todas as configurações regionais especificadas. Seu método 
.toString() produz uma sequência padrão regional formatada.
 const krLocale = new Intl.Locale( 'ko', {  script: 'Kore', region: 'KR',  hourCycle: 'h12', calendar: 'gregory' } ); console.log( krLocale.baseName );  
Aqui você pode ler sobre identificadores e tags de localidade em Unicode.
→ Suporte
- TC39: Etapa 3
- Chrome: mais de 74
- Nó: 12+
Promessas
A partir de agora, o JS possui os métodos estáticos 
Promise.all() e 
Promise.race() . O 
Promise.all([...promises]) retorna uma promessa que foi resolvida com êxito depois que todas as promessas passadas ao método como argumento são resolvidas. Essa promessa é rejeitada no caso de pelo menos uma das promessas transferidas para ela ser rejeitada. O 
Promise.race([...promises]) retorna uma promessa, que é resolvida após a resolução de qualquer uma das promessas transferidas e é rejeitada se pelo menos uma dessas promessas for rejeitada.
A comunidade de desenvolvedores de JS estava desesperada por um método estático, a promessa retornada que seria resolvida depois que todas as promessas passadas fossem concluídas (permitidas ou rejeitadas). Além disso, precisávamos de um método semelhante ao 
race() , que retornasse uma promessa aguardando a resolução de qualquer uma das promessas passadas.
Método Promise.allSettled ()
O método 
Promise.allSettled() aceita uma variedade de promessas. A promessa retornada por ele é permitida depois que todas as promessas são rejeitadas ou permitidas. O resultado é que a promessa retornada por esse método não precisa de um 
catch .
O fato é que essa promessa é sempre resolvida com sucesso. O bloco 
then recebe 
status e 
value de cada promessa na ordem em que aparecem.
 var p1 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val1' ), 2000 ) ); var p2 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val2' ), 2000 ) ); var p3 = () => new Promise(  (resolve, reject) => setTimeout( () => reject( 'err3' ), 2000 ) ); var p = Promise.allSettled( [p1(), p2(), p3()] ).then(  ( values ) => console.log( values ) );  
→ Suporte
▍ Método Promise.any ()
O método 
Promise.any() é semelhante ao 
Promise.race() , mas a promessa retornada por ele não executa o 
catch quando uma das promessas passadas para esse método é rejeitada.
Em vez disso, ele aguarda a resolução de todas as promessas. Se nenhuma promessa foi permitida, o bloco 
catch será executado. Se alguma das promessas for resolvida com êxito, 
then será executada.
Sumário
Neste artigo, vimos algumas das inovações em JavaScript discutidas na conferência 
Google I / O 2019 . Esperamos que você encontre algo útil entre eles.
Caros leitores! O que você sente falta especialmente em JavaScript?
