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?
