# O que tem de novo no ES2020(es11)

Vamos ver mais de perto as coisas incríveis que chegaram agora na nova especificação do *ECMAScript*! 🤩

Todo ano uma nova versão da especificação *ECMAScript* sai com as propostas de *features,* para isso o [comitê da TC39 faz um exaustivo processo](https://tc39.es/process-document/)refinando as propostas até serem serem aceitas e passaram para seu estado final,o [stage 4](https://github.com/tc39/proposals/blob/master/finished-proposals.md), que define o que estará presente no proximo *draft*.Essas *features* serão consideradas **estáveis** assim que dois navegadores as implementarem.

Esse processo garante uma melhora constante no estado da arte do Javascript 👩‍🎨.

Todas as features para a especificação de 2020(*ES2020*) \*\*estão finalizadas,\*\*significando que estão prontas para serem **implementadas em navegadores, engines e ferramentas!**

➡️ BigInt➡️ Classes Privadas➡️ Optional Chaining➡️ Nullish coalescing Operator➡️ String.prototype.matchAll➡️ globalThis➡️ for-in mechanics➡️ Promise.allSettled➡️ Dynamic Imports➡️Module Namespace Exports➡️ import.meta

# **As propostas 🖋**

# [**BigInt**](https://github.com/tc39/proposal-bigint) **🧮**

Quem está habituado a usar números em JS já sofreu muito em relação a limitação do seu tipo **number,** que não passa de um double de 64 bits, tendo assim uma limitação de até um certo número que podemos fazer operações de forma “segura”.

```plaintext
// Número máximo seguro no JS
Number.MAX_SAFE_INTEGER // 9007199254740991
```

Para isso é comum dependermos de bibliotecas externas para tentar lidar de forma mais segura com valores altos.

`BigInt` é agora o **sétimo tipo primitivo** dentro da linguagem, servindo somente pra lidar somente com precisão de inteiros. Pois uma variável deste tipo pode representar 2⁵³ números.

Com a nova especificação podemos indicar o tipo `BigInt` somente colocando uma letra `n` no final do número, denotado para a engine Javascript(v8 ou qualquer outra) como o número ser tratado.

```plaintext
const numeroGrande = 100000000000000000000000000000n;
console.log(numeroGrande * 2n); // 200000000000000000000000000000n
```

Podemos fazer *casting* para esse novo tipo desta forma.

```plaintext
console.log(BigInt(Number.MAX_SAFE_INTEGER))
// 9007199254740991n
```

É importante lembrar que essa coersão de `Number` para `BigInt` pode causar perda de precisão então o ideal é já definir números como `BigInt`quando se tem a certeza que eles podem ser grandes.

`BigInt` já foi implementado nos maiores navegadores como Chrome, Firefox, opera e a versão 10.4 do Node.js e está bem **estável ✅**

**📖**[**Especificação**](https://tc39.es/ecma262/#sec-bigint-objects)**🗼**[**Plugin Babel**](https://babeljs.io/docs/en/babel-plugin-syntax-bigint)

# [**Classes Privadas**](https://github.com/tc39/proposal-private-methods) **🔒**

*JS* sempre foi uma linguagem orientada a objetos mas por sua implementação com base em protótipo ao invés de classes, apesar de termos a sintaxe especial de `Class`desde de a *ES2015,* por conflitos de decisões de implementação não tínhamos como fazer métodos ou campos privados nativamente.

Quando usamos classes em Javascript temos como padrão nomear elementos privados com um `_`na frente como meio de diferenciação.

Com a nova especificação colocar o sinal de `#`na frente da variável ou função já vai definir que o **não se deve ter acesso a ele em outros contextos além da própria classe**.

Apesar de parecer contra intuitivo, essa decisão se deve exatamente ao fato de que muitas bibliotecas já aderiram o sublinhado `_` como meio de marcar campos privados, sendo um meio de evitar alterações já existentes.

Isso pode causar um estranhamento também pra quem vem do *Typescript*cuja sintaxe já amplamente conhecida para definir se algo é privado também é o `_` .

Dessa forma podemos escrever classes similares a essa:

```plaintext
class Counter {
  #x = 0;             // Define uma variável privada
  increment() {
    this.#x++;        // Incrementa a variável privada
  }
  decrement() {
    this.#x--;        // Decrementa a variável privada
  }
  getX(){
    return this.#x;
  }
}const c = new Counter();console.log(c.getX()); // 0 -> Valor é exposto pelo metodo getX
```

Tentar pegar o valor da variável privada diretamente não é viável pois ela não pode ser acessada fora do contexto da classe.

```plaintext
c.#x => 🙅‍♀Uncaught SyntaxError: Private field '#x'
```

Os métodos modificam o campo x e o resultado final retornado por por `getX` é o valor -1.

```plaintext
c.increment(); 
c.decrement();
c.decrement();
console.log(c.getX()); // -1 -> Valor é modificado e depois exposto
```

Supondo que no meu exemplo não quero que o contador chegue em valor abaixo de 0 e quero criar uma função auxiliar privada para fazer essa verificação.

```plaintext
class Counter {
  #x = 0;     
  increment() {
    this.#x++;       
  }
  #isPositive() {
    return this.#x > 0
  }
  decrement() {
    if (this.#isPositive()) this.#x--;  
  // Chama o método privado para verificar se o valor x é positivo
  }
  getX(){
    return this.#x;
  }
}const c = new Counter();
```

Assim como a propriedade privada, não posso chamar o método novo fora do contexto da classe.

```plaintext
c.#isPositive() => 🙅‍♀Uncaught SyntaxError: Private method '#x'
```

Desta forma ao chamar a função decrement podemos ter a garantia que nosso valor não será negativo.

```plaintext
c.decrement();
console.log(c.getX()); // 0
```

Isso é de extrema importante pois até então tínhamos dificuldade de seguir os **princípios de SOLID** pois não tínhamos como suprir o **Open/Closed**principle.

Essa feature já está na ultima versão do *Chrome* e do *Node v12*.

**📖**[**Especificação**](https://tc39.es/proposal-private-methods/)**🗼**[**Plugin Babel**](https://babeljs.io/docs/en/babel-plugin-proposal-private-methods)

# [**Optional Chaining Operator**](https://github.com/tc39/proposal-optional-chaining) **❓**

Quem nunca passou ou ouviu falar do famoso *“Cannot read property of undefined”*? Javascript pode ser *tricky* quando estamos lidando com valores *nulos* ou *undefined*.

Pelo dinamismo do Javascript precisamos muitas vezes fazer **múltiplas verificações para conseguir pegar propriedades de qualquer objeto**para tentar evitar receber um erro pois uma delas está nula.

Supondo um objeto com dados de um "usuário" que pode\*(ou não)\* conter informações do perfil de uma pessoa.

```plaintext
user // undefined
user.profile // Error : Cannot read property of undefined
user.profile.name // Error : Cannot read property of undefined
```

Quando tentamos pegar a propriedade de um objeto, o código espera que seja um objeto válido, jogando um erro caso o seu valor seja inesperado.

Quando não temos a garantia dos valores e temos de pegar por exemplo, uma propriedade `name` em segundo nível do objeto teríamos de fazer diversas verificações.

```plaintext
if (user != undefined && user.profile != undefined) {
 user.profile.name 
}
```

Adicionando o novo operador interrogação antes do ponto nós conseguimos interagir com o caminho opcional. Caso ele exista, temos acesso ao resultado esperado.

```plaintext
const user = {profile: name: "Maria"}
user?.profile?.name // “Maria”
```

Caso algum valor comparado pelo operador não exista ele retorna apenas um *undefined* sem mais erros.

```plaintext
const user = {}user?.profile?.name // Undefined
```

Isso não se limita a objetos ou arrays mas também pode ser usado em funções a serem executadas.

```plaintext
user.profile.checarAlgo?.(...argumentos)
```

Essa sintaxe também pode ser usada para acesso dinâmico da propriedade

```plaintext
user.profile?.[nomeDaPropriedade]
```

Isso é especialmente interessante quando queremos um valor dentro de uma estrutura muito grande que precisamos sempre ficar checando se cada parte da estrutura existe ou não.

```plaintext
// Com operador
a?.b[3].c?.(x).d
// Sem operador
a == null ? undefined : a.b[3].c == null ? undefined : a.b[3].c(x).d
```

O operador de **Optional Chaining** permite lidar com a talvez existência de valores de forma limpa, consistente e sem que a gente se repita fazendo múltiplas verificações desnecessárias para o mesmo elemento. A sintaxe foi inspirada de linguagens como *C#* e *Swift* e também certamente do *Typescript*, que já tem essa funcionalidade nativa.

A funcionalidade já está implementada nos principais navegadores, engines e ferramentas!

**📖**[**Especificação**](https://tc39.es/proposal-private-methods/)**🗼**[**Plugin Babel**](https://babeljs.io/docs/en/babel-plugin-proposal-private-methods)

# [**Nullish Coalescing Operator**](https://github.com/tc39/proposal-nullish-coalescing) **⏸**

É bem comum fazermos verificações para checar se um valor especifico é **falsey**(*null, undefined, etc)* para tratarmos da forma mais apropriada para não quebrarmos nosso código ou expormos acidentalmente esses valores para o usuário.

Quando queremos acessar propriedades de um objeto que não temos certeza de sua existência é comum usarmos um valor *default*. Tentamos algo similar a isso:

```plaintext
user.profile.name == undefined ? “Anonymous” : person.profile.name
user.profile.age == undefined ? 0 : person.profile.age
```

Também podemos tentar expressar a mesma coisa por meio do operador barra-barra ou OR =&gt; ||.

```plaintext
false || “Texto teste” // Texto teste
undefined || “Texto teste” // Texto teste
null ||"Texto teste" // Texto teste
NaN || "Texto teste" //Texto teste
```

Essa solução é realmente ótima quando queremos lidar com qualquer tipo que consideramos **"Falsey"**

O **Nullish Coalescing** nos apresenta um operador de duas interrogações (??) que nos trás uma verificação mais *type strict p*ermitindo um valor *default* **apenas** quando temos um *null* ou *undefined*.

```plaintext
false ?? “Texto teste” // false
undefined ?? “Texto teste” // Texto teste
null ?? ”Texto teste” // Texto teste
NaN ?? “Texto teste” // NaN
```

Podemos simplificar o exemplo anterior desta forma:

```plaintext
user.profile.name == undefined ? “Anonymous” : person.profile.name
user.profile.name ?? “Anonymous”
```

Supondo que no nosso mesmo objeto `user`, podemos dentro de profile ter tanto um `name` quanto um `nickname.`Se em um campo de nome devo mostrar o `name` **OU** o`nickname` **OU** um valor padrão, nossa solução comum seria algo similar a:

```plaintext
if (person.profile.nickname == undefined) { 
  if(person.profile.name == undefined) {
    “Anonymous”
  } else {
    return person.profile.name
  }
} else {
  return person.profile.nickname
}
```

Com nosso novo operador se torna apenas:

```plaintext
person.profile.nickname ?? person.profile.name ?? “Anonymous”.
```

Essa sintaxe já é [bem conhecida](https://en.wikipedia.org/wiki/Null_coalescing_operator) em outras linguagens como *C#* e *Swift,* está presente no *PHP* desde sua versão 7 e já está começando a ser implementada nos maiores navegadores.

**📖**[**Especificação**](https://tc39.es/proposal-nullish-coalescing/)**🗼**[**Plugin Babel**](https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator)

# [**String.protype.matchAll**](https://github.com/tc39/proposal-string-matchall) **💕**

O novo metodo`matchAll()` está relacionado a expressões regulares.Ele recebe uma expressão como argumento e retorna um iterador com todos os resultados que deram "*match*" com essa expressão.

Podemos acessar os casos iterando o seu resultado.

```plaintext
const onlyABC = /[a-c]/g
const str = 'abc'
const matches = str.matchAll(onlyABC)for (const match of matches) {
  console.log(match);
}// ["a", index: 0, input: "abc", groups: undefined]
// ["b", index: 0, input: "abc", groups: undefined]
// ["c", index: 0, input: "abc", groups: undefined]
```

Após a interação pelo *for..of* nosso iterador fica cansado, então temos de chamar o `matchAll()` novamente se requeremos os resultados novamente.

```plaintext
const arrMatches = [...str.matchAll(onlyABC)]// [["a", index: 0, input: "abc", groups: undefined],
    ["b", index: 0, input: "abc", groups: undefined],
    ["c", index: 0, input: "abc", groups: undefined]]
```

Ok, mas qual o beneficio?Agora conseguimos **um resultado mais complexo para nossa *regex* além do *match* em si**, \*\*e isso fica visível em casos mais complexos em temos diversos agrupamentos.

```plaintext
const getTest = /t(e)(st(\d?))/g;
const str = 'test1test2'const arrMatches= [...str.matchAll(getTest)];

array[0];
// ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4]
array[1];
// ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4]str.match(getTest); 
// Array ['test1', 'test2']
```

A escolha de retornar um iterador é por uma mera questão de performance, já que podemos facilmente coletar esses valores por meio do *spread operador* como no exemplo acima.Essa feature já está também vastamente implementada.

**📖**[**Especificação**](https://tc39.es/proposal-string-matchall/)

# **Standardized globalThis object 🌍**

O que para alguns é um monstro para outros pode ser benção, agora temos padronizado o **THIS GLOBAL**. Ou seja, um contexto da aplicação global independente de *runtime*.

O `globalThis` se refere ao objeto global, independente de onde você está executando o código. Sendo assim você pode em produção para um projeto multiplataforma escrever isso:

```plaintext
globalThis.variavelGlobalzassa = "Irraaa 🤠🐎"
```

Brincadeiras a parte, essa padronização se deve ao fato que por JS ser multiplataforma e portanto, um único código pode rodar no Node, no navegador ou em qualquer outro contexto.Sendo assim, fica difícil ter um objeto global sem uma padronização se isso vai ser em um `window` (Browser) ou`global` (Node) por exemplo.

**📖**[**Especificação**](https://tc39.es/proposal-global/)

# **Promise.allSettled 🚦**

O metodo`Promise.allSettled` recebe um *array* de *Promises* e só se resolve quando todas as elas estiverem resolvidas, seja como *fulfilled* ou \*rejected,\*com o estado de cada uma delas.

Ou seja, com ele podemos criar uma nova *Promise* que só retorna quando todas as *Promises* passadas forem concluídas, **independente de resultado**, sem a necessidade de um encadeamento.

O método retorna um *array* com o status das *Promises* com o seu respectivo valor, caso *fullfilled,* ou a razão da falha, caso *rejected*.

Nesse exemplo temos colocamos duas promises no `Promise.allSettled` , uma com resolução e outra com falha, e damos console.log no resultado!

```plaintext
const stuff1 = new Promise((res, rej) => res({x: 10, test: "🤠"}));
const stuff2= new Promise((res, rej) => rej(Error("Deu ruim 😭")));Promise.allSettled([stuff1, stuff2])
  .then(data => console.log(data)); 
// [ 
//   Object { status: "fulfilled", value: {x: 10, test: "🤠"}},
//   Object { status: "rejected", reason: "Deu ruim 😭"} 
// ]
```

Temos como resultado um array com dois objetos, ambos com o status de resolução da *Promise*. A que foi resolvida tem uma propriedade `value` que contêm o conteúdo da *Promise* e que falhou tem a propriedade \*\*`reason`*q*ue fala a razão do erro.

Já tentávamos fazer algo similar resolvendo múltiplas promises simultâneas com o `Promise.all` .

```plaintext
Promise.all([stuff1, stuff2])
  .catch(err => console.log(err));  // Deu ruim 😭
```

Se colocássemos as duas promises o `Promise.all` joga pra cima a falha do `stuff2`para que você trate e ignora completamente as *Promises* que foram resolvidas. **Não tínhamos até então um método que “não ligasse” pros resultados de cada uma das *Promises*.**

A motivação vem da implementação dos [4 combinators de promises](https://v8.dev/features/promise-combinators), que são os principais casos implementados em bibliotecas ou linguagens para lidar com assincronismo.

Nele temos o `Promise.all` e o`Promise.race` que já foram especificados na *ES2015,* o `Promise.allSettled` , e um futuro metodo a ser incluído em uma **próxima proposta** chamado `Promise.any` .

O `Promise.any` receberia também uma lista de *Promises* e retornaria quando qualquer uma fosse resolvida.

**📖**[**Especificação**](https://tc39.es/proposal-promise-allSettled/)

# [**for-in mechanics**](https://github.com/tc39/proposal-for-in-order) **🎡**

Quem acompanhou as mudanças sabe da existência dessa feature. Aparentemente a especificação da forma como for-in deve ser implementada foi na verdade apenas mais refinada pois a sua ultima versão foi pouco especifica em relação a que ordem o `for (x in y)`deve rodar levando a *engines* não entraram em um consenso sobre como implementar.

**📖**[**Especificação**](http://tc39.es/proposal-for-in-order/)

# [**Dynamic Import / Import()**](https://github.com/tc39/proposal-dynamic-import) **🚢**

O import dinâmico retorna uma uma promise para o objeto do modulo do namespace que foi requisitado. Sendo assim, **agora poderemos colocar um import dentro de uma variável e chamar usando async/await .**

Para que isso é importante? Podemos importar nossos arquivos de forma “*Lazy*” ou seja, **apenas executar código dos arquivos conforme queremos.**

Isso garante um controle da execução código muito maior em *runtime*podendo impactar muito na performance pois **executar todos os arquivos que são importados imediatamente pode ser um *overhead.***

Se por exemplo, estou usando funções de utilidade de outro arquivo ou pacote que são utilizadas apenas algum momento especifico do meu código.*Será que faz sentido mais importá-las quando o arquivo foi executado ou quando forem(e se forem) realmente utilizadas?*

```plaintext
//utils.js...muitas funções e coisas...const add = (x, y) => x + y;export { add };
```

Se estou fazendo uso dele em outro arquivo podemos importá-lo apenas antes de usar a função importada em especifico.

```plaintext
const doMathStuff = async (x, y) => {
    const math = await import('./utils.js');
    console.log(math.add(5, 10));
};
```

Em *runtime* essa função não vai ser carregada a não ser que chamada, portanto pode até mesmo **nunca ser carregada se nunca for usada**.

Isso é extremamente crucial por exemplo em *front-end* em que queremos minimizar o máximo possível o conteúdo sendo executado. Muito código sendo executado inconsequentemente ao abrir um site pode ser bem custoso\*([ver “V8 Start-up Performance”](https://medium.com/reloading/javascript-start-up-performance-69200f43b201)).\*

Isso é conhecido como *code splitting* e muito provávelmente seu código já está sendo pelo menos um pouco otimizado pelo próprio *babel* com *webpack*, ou qualquer outro *module bundle* dessa forma.

O *webpack* por exemplo faz algo chamado ["Tree shaking"](https://webpack.js.org/guides/tree-shaking/) , em que ele basicamente monta uma arvore de dependências do seu próprio código e otimiza por exemplo, removendo o que não está sendo usado.

Os imports dinâmicos ficam de fora do *Tree Shaking* do *webpack* *(ver*[*Dynamic Import and Tree Shaking in JavaScript*](https://medium.com/better-programming/dynamic-import-and-tree-shaking-in-javascript-ddc2f3cd69f)*)*, então é importante questionar quando vale a pena deixar o controle na nossa mão ou em outras ferramentas.

**📖**[**Especificação**](https://github.com/tc39/proposal-export-default-from)**🗼**[**Plugin babel**](https://babeljs.io/docs/en/babel-plugin-proposal-export-default-from)**🌲**[**Otimização JS com tree shaking**](https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking)

# [**Module Namespace Exports**](https://github.com/tc39/proposal-export-ns-from) **🛄**

Nos módulos podemos usar a seguinte sintaxe para importarmos todos os elementos de por exemplo, um arquivo `utils`:

```plaintext
import * from './utils.js'
```

Mas não podíamos exportar de forma similar **nativamente** e tínhamos de exportar o próprio modulo dentro de um objeto.

```plaintext
import default as utils from './utils.js'
export { utils }
```

Mas agora temos uma sintaxe similar para exportar todo o conteúdo do módulo de forma similar!

```plaintext
export * from './utils.js'
```

Também podemos renomear o conteúdo exportado como nos exemplos:

```plaintext
export * as utils from './utils.js'
export { add as soma } from  './utils.js'
```

A ideia é bem simples mas essa simetria deixa mais consistente a forma como lidamos com nossos projetos.

**📖**[**Especificação**](https://tc39.es/proposal-export-ns-from/)**🗼**[**Plugin Babel**](https://babeljs.io/docs/en/babel-plugin-proposal-export-namespace-from)

— — — — —

"Quero usar essas funcionalidade tipo, **AGORA**!!"

Basta modificar o seu arquivo`.babelrc` alguns destes novos plugins

```plaintext
{
  "plugins": [
    "@babel/plugin-proposal-nullish-coalescing-operator",
    "@babel/plugin-proposal-optional-chaining",
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-private-methods",
    "@babel/plugin-syntax-bigint"
  ]
}
```

Caso você não tenha nada configurado a forma mais simples seria usando o [Parcel bundler](https://parceljs.org/) no seu projeto instalando-o como dependência

```plaintext
$ yarn add parcel-bundler
```

E em seguida configurando nos scripts do seu *package.json* para que ele execute os seu projeto.

```plaintext
// package.json..."scripts": {
  "start": "parcel index.js"
},
```

# **Conclusão**

**Javascript é uma linguagem viva** e vemos nos últimos anos uma evolução constante para melhorar o desenvolvimento web e isso certamente é uma tarefa difícil para uma uma comunidade também crescendo e evoluindo muito rápido com a linguagem.

Espero que vocês tenham gostado!! 👏 👏 👏 👏 👏 👏

\*\*Quem gostou bate palminha pra que o artigo alcance outros amiguinhos.\*\**❤️🧡💛💚💙💜.*

[https://github.com/tc39/proposals/blob/master/finished-proposals.md](https://github.com/tc39/proposals/blob/master/finished-proposals.md)
