Inovações ES2020 que eu realmente gosto

O JavaScript vem se desenvolvendo muito rapidamente nos últimos anos. Isso é especialmente verdade no período após o lançamento do padrão ES6 em 2015. Desde então, muitos recursos excelentes apareceram no idioma. Muito novo foi proposto para inclusão no padrão ES2020. Uma lista final de recursos já foi formada, cuja aparência pode ser esperada no padrão após sua aprovação. Esta é uma boa notícia para todos os entusiastas do JS. O autor do artigo, cuja tradução estamos publicando hoje, diz que entre essas oportunidades há aquelas com as quais ele está especialmente satisfeito. Antes de aparecerem, era muito mais difícil para ele escrever código nas situações em que são aplicáveis. Segundo ele, se eles tivessem aparecido no idioma anteriormente, teriam poupado muito tempo e esforço.





Correntes opcionais


O encadeamento opcional é, para mim, um dos recursos mais interessantes do padrão ES2020. Eu escrevi muitos programas nos quais esse recurso seria extremamente útil. 

As cadeias opcionais permitem organizar o acesso seguro a propriedades profundamente incorporadas de objetos sem a necessidade de verificar a existência de cada um deles. Veja como esse recurso funciona.

Primeiro, observe o código que precisava ser escrito antes do advento das cadeias opcionais.

Before Código antes do aparecimento de cadeias opcionais


const user = {
   firstName:"Joseph",
   lastName:"Kuruvilla",
   age:38,
   address:{
      number:"239",
      street:"Ludwig Lane",
      city:"Chennai",
      zip:"600028",
   prop1:{
    prop2:{
     prop3:{
      prop4:{
       value:'sample'
      }
     }
    }
   }
   }
}
if(user && user.address){
 console.log(user.address.zip);
 //600028
}
if(user && user.address && user.address.prop1 && user.address.prop1.prop2 && user.address.prop1.prop2.prop3 && user.address.prop1.prop2.prop3.prop4){
 console.log(user.address.prop1.prop2.prop3.prop4.value);
 //sample
}
//    
console.log(user.address.prop102.po);
//Error

Como você pode ver, para evitar a ocorrência de erros, parece Cannot read property 'po' of undefinedque é necessário, em cada nível de aninhamento, verificar as propriedades quanto à sua existência. Com um aumento na profundidade do aninhamento de entidades, o número de propriedades verificadas também aumenta. Isso significa que o próprio programador precisa escrever um código que o proteja de propriedades que, quando acessadas, podem executar os valores de nullou undefined.

After Código após o aparecimento de cadeias opcionais


Escrever código como o que acabamos de revisar tornou muito mais fácil com o advento de cadeias opcionais. Para organizar o trabalho seguro com propriedades profundamente incorporadas de objetos, basta usar o operador ?.. Isso evita a necessidade de verificar independentemente os valores em nulle undefined.

Aqui está o que parece:

const user = {
   firstName:"Joseph",
   lastName:"Kuruvilla",
   age:38,
   address:{
      number:"239",
      street:"Ludwig Lane",
      city:"Chennai",
      zip:"600028",
   prop1:{
    prop2:{
     prop3:{
      prop4:{
       value:'sample'
      }
     }
    }
   }
   }
}
console.log(user?.address?.zip);
//600028
console.log(user?.address?.prop1?.prop2?.prop3?.prop4?.value);
//sample
//    
console.log(user?.address?.prop102?.po);
//undefined

Bem, não está bem? Graças a essa inovação, o ES2020 tornou possível eliminar um grande número de linhas de código.

Validando apenas valores nulos e indefinidos


Verificar valores apenas em nulle undefined(Nullish Coalescing) é uma daquelas características que realmente me encantaram, mesmo quando as possibilidades estavam no estágio de proposta. Muitas vezes me deparei com a necessidade de escrever funções especializadas para realizar as verificações apropriadas.

Sabe-se que o JavaScript tem significados "falsos" e "verdadeiros". Agora podemos dizer que valores "zero" foram adicionados a eles. Esses valores incluem nulle undefined. Com termos de JavaScript de "falso" são strings vazias, o número 0, os valores undefined, null, false, NaN. Ou seja, por exemplo, uma certa expressão para verificar o valor de "falsidade" funcionará em uma sequência vazia e no valorundefinede muito mais sobre o que. E a expressão para verificar o valor de "zero" retornará trueapenas para nulle undefined. Talvez essa oportunidade não pareça tão maravilhosa para você pessoalmente, mas, de fato, é muito, muito importante.

Vejamos alguns exemplos.

Code O código até a capacidade de verificar valores apenas em nulos e indefinidos


Recentemente, eu estava trabalhando em um projeto no qual precisava implementar a funcionalidade de alternar entre temas claros e escuros. Ao mesmo tempo, tive que verificar o estado do controle, descobrir se ele corresponde ao valor de trueou false. Se o usuário não definiu nenhum valor, por padrão, ele deve ser igual true. Aqui está como eu resolvi esse problema antes da possibilidade de verificar valores apenas em nulle undefined:

const darkModePreference1 = true
const darkModePreference2 = false
const darkModePreference3 = undefined
const darkModePreference4 = null
const getUserDarkModePreference = (darkModePreference) => {
  if (darkModePreference || darkModePreference === false) {
    return darkModePreference
  }
  return true
}
getUserDarkModePreference(darkModePreference1) 
// true
getUserDarkModePreference(darkModePreference2) 
// false
getUserDarkModePreference(darkModePreference3) 
// true
getUserDarkModePreference(darkModePreference4) 
// true

After Código após a possibilidade de verificar valores apenas em nulos e indefinidos


Depois que esse recurso aparecer no idioma para verificação nulle undefinedoperador suficiente ??. Nesse caso, você pode fazer sem um operador condicional if:

const darkModePreference1 = true
const darkModePreference2 = false
const darkModePreference3 = undefined
const darkModePreference4 = null
const getUserDarkModePreference = (darkModePreference) => {
  return darkModePreference ?? true;
}
getUserDarkModePreference(darkModePreference1) 
// true
getUserDarkModePreference(darkModePreference2) 
// false
getUserDarkModePreference(darkModePreference3) 
// true
getUserDarkModePreference(darkModePreference4) 
// true

Aqui acontece o seguinte: se a variável darkModePreferencecontiver um valor "zero", o valor será retornado true. Isso facilita a escrita do código, é compacto e fácil de entender.

Importações dinâmicas


As importações dinâmicas contribuem para um desempenho mais eficiente dos aplicativos. Essa tecnologia permite importar arquivos JS dinamicamente, na forma de módulos, sem envolver ferramentas adicionais. Além disso, se o módulo não for necessário, ele não será importado. Antes do ES2020, os módulos eram importados, independentemente de serem usados ​​pelo aplicativo ou não.

Por exemplo, suponha que precisamos implementar a funcionalidade de carregar um determinado arquivo no formato PDF.

Considere, como sempre, as opções antigas e novas para resolver esse problema.

Before Código antes do suporte para importações dinâmicas


Com base na situação real, podemos esperar que a capacidade de baixar materiais em formato PDF não seja usada por todos os visitantes da página. Mas o módulo correspondente, de qualquer maneira, precisa ser importado para o código. Isso significa que o módulo, necessário ou não, será carregado quando a página carregar.

import { exportAsPdf } from './export-as-pdf.js'
const exportPdfButton = document.querySelector('.exportPdfBtn');
exportPdfButton.addEventListener('click', exportAsPdf);

Isso cria uma carga adicional no sistema, que pode ser facilitada usando o carregamento lento dos módulos. Isso pode ser feito com a ajuda da tecnologia de separação de código, disponível no webpack ou em outros carregadores de módulos (e seu uso por si só significa desperdício de uma certa quantidade de recursos do sistema).

Mas agora, graças ao ES2020, temos uma maneira padrão de carregar dinamicamente módulos, o que nos permite prescindir de empacotadores.

After Código após o aparecimento do suporte para importações dinâmicas


const exportPdfButton = document.querySelector('.exportPdfBtn');
exportPdfButton.addEventListener('click', () => {
  import('./export-as-pdf.js')
    .then(module => {
      module.exportAsPdf()
    })
    .catch(err => {
      //      -  
    })
})

Como você pode ver, agora você pode organizar o carregamento lento dos módulos carregando somente quando precisar do módulo apropriado. Isso reduz a carga do sistema e aumenta a velocidade de carregamento da página.

Construir Promise.allSettled


Se você precisa executar alguma ação somente se todas as promessas foram resolvidos com êxito, você pode usar o método Promise.all(). É verdade que este método tem uma desvantagem. O método lançará um erro se pelo menos uma promessa passada a ele for rejeitada. Isso significa que a ação necessária não será executada até que todas as promessas sejam resolvidas com sucesso.

Você pode não precisar disso. Talvez o seguinte cenário seja o seu caso: “O resultado não é importante para mim. Eu preciso que o código seja executado após a conclusão de todas as promessas. ” Nesse caso, o método é útil para você Promise.allSettled(). A promessa correspondente é resolvida com sucesso somente após a conclusão de outras promessas. Não importa se eles funcionaram com ou sem êxito.

▍ Código usando a construção Promise.all


const PromiseArray = [
    Promise.resolve(100),
    Promise.reject(null),
    Promise.resolve("Data release"),
    Promise.reject(new Error('Something went wrong'))];
Promise.all(PromiseArray)
  .then(data => console.log('all resolved! here are the resolve values:', data))
  .catch(err => console.log('got rejected! reason:', err))
//got rejected! reason: null

Aparentemente, Promise.allocorre um erro após a rejeição de uma das promessas transferidas para ele.

▍ Código que usa a construção Promise.allSettled


const PromiseArray = [
    Promise.resolve(100),
    Promise.reject(null),
    Promise.resolve("Data release"),
    Promise.reject(new Error('Something went wrong'))];
Promise.allSettled(PromiseArray).then(res =>{
console.log(res);
}).catch(err => console.log(err));
//[
//{status: "fulfilled", value: 100},
//{status: "rejected", reason: null},
//{status: "fulfilled", value: "Data release"},
//{status: "rejected", reason: Error: Something went wrong ...}
//]

E aqui, embora algumas das promessas sejam rejeitadas, ele Promise.allSettledretorna os resultados emitidos por todas as promessas transferidas para ele.

Outros recursos notáveis


Type Tipo de dados BigInt


O novo tipo de dados BigIntpermite que você trabalhe com números cujo tamanho excede o tamanho dos números com os quais você poderia trabalhar em JavaScript antes de aparecer ( pow(2,53)-1). É verdade que esse tipo de dado não é compatível com o que estava no idioma anterior. O padrão IEEE 754, que é a base para trabalhar com números em JavaScript, não suporta os números possíveis de trabalhar comBigInt

▍ Método String.prototype.matchAll


O método String.prototype.matchAll()está relacionado a expressões regulares. Ele retorna um iterador, permitindo que você trabalhe com todas as correspondências encontradas em uma string usando uma expressão regular , incluindo grupos .

▍ Propriedade global globalThis


A propriedade global globalThismantém uma referência ao objeto global correspondente ao ambiente em que o código é executado. No navegador, o objeto global é representado pelo objeto window. No Node.js, este é um objeto global. Nos trabalhadores da Web, este é um objeto self.

Quais inovações você mais gosta no ES2020?


All Articles