Como Usar Novidades do ECMAScript: ES2022, ES2023 e ES2024 na Prática em Produção Já leu

ES2022: Top-Level Await e Class Fields O ES2022 trouxe melhorias significativas para módulos e orientação a objetos. O top-level await permite usar diretamente no corpo de um módulo, sem envolvê-lo em uma função . Isso simplifica a inicialização de dados antes da execução do código principal. Os campos de classe privada ( ) e o operador para verificação trazem encapsulamento real. Diferente de convenções anteriores, campos privados são verdadeiramente inacessíveis fora da classe. O método em arrays permite acesso negativo elegante, retorna o último elemento sem contar o tamanho. ES2023: Array Grouping e Métodos de String Melhorados O e revolucionaram agregação de dados, substituindo lógicas complexas por uma única função. Este método agrupa elementos conforme um critério definido, retornando um objeto ou mapa com as categorias como chaves. Os métodos e implementam a busca em ordem reversa de forma nativa. , e criam cópias ordenadas/modificadas sem alterar o array original—crucial para programação imutável. ES2024: Promise.withResolvers e Array Methods Finais O

ES2022: Top-Level Await e Class Fields

O ES2022 trouxe melhorias significativas para módulos e orientação a objetos. O top-level await permite usar await diretamente no corpo de um módulo, sem envolvê-lo em uma função async. Isso simplifica a inicialização de dados antes da execução do código principal.

// Antes: precisava de uma IIFE ou função async
// Depois: ES2022
const dados = await fetch('https://api.exemplo.com/dados').then(r => r.json());
console.log(dados);

Os campos de classe privada (#) e o operador in para verificação trazem encapsulamento real. Diferente de convenções anteriores, campos privados são verdadeiramente inacessíveis fora da classe. O método .at() em arrays permite acesso negativo elegante, array.at(-1) retorna o último elemento sem contar o tamanho.

class Usuario {
  #senha; // campo privado verdadeiro

  constructor(nome, senha) {
    this.nome = nome;
    this.#senha = senha;
  }

  verificarSenha(teste) {
    return teste === this.#senha;
  }

  static criar(dados) { // static inicializer blocks
    return new Usuario(dados.nome, dados.senha);
  }
}

const arr = [10, 20, 30];
console.log(arr.at(-1)); // 30
console.log(arr.at(-2)); // 20

ES2023: Array Grouping e Métodos de String Melhorados

O Object.groupBy() e Map.groupBy() revolucionaram agregação de dados, substituindo lógicas complexas por uma única função. Este método agrupa elementos conforme um critério definido, retornando um objeto ou mapa com as categorias como chaves.

const usuarios = [
  { nome: 'Ana', role: 'admin' },
  { nome: 'Bruno', role: 'user' },
  { nome: 'Carlos', role: 'admin' },
  { nome: 'Diana', role: 'user' }
];

const porRole = Object.groupBy(usuarios, u => u.role);
// Resultado:
// {
//   admin: [{ nome: 'Ana', role: 'admin' }, { nome: 'Carlos', role: 'admin' }],
//   user: [{ nome: 'Bruno', role: 'user' }, { nome: 'Diana', role: 'user' }]
// }

const porRoleMap = Map.groupBy(usuarios, u => u.role);
console.log(porRoleMap.get('admin')); // array de admins

Os métodos .findLast() e .findLastIndex() implementam a busca em ordem reversa de forma nativa. .toSorted(), .toReversed() e .toSpliced() criam cópias ordenadas/modificadas sem alterar o array original—crucial para programação imutável.

const numeros = [5, 12, 8, 130, 44];

const ultimo = numeros.findLast(n => n > 10); // 44
const indice = numeros.findLastIndex(n => n > 10); // 4

const ordenado = numeros.toSorted((a, b) => a - b); // cópia ordenada
const invertido = numeros.toReversed(); // cópia invertida
console.log(numeros); // original intacto: [5, 12, 8, 130, 44]

ES2024: Promise.withResolvers e Array Methods Finais

O Promise.withResolvers() extrai resolve e reject do construtor da Promise, tornando padrões como executores repetidos mais limpos. Em vez de envolver código em new Promise(), você obtém a promise e os controladores separadamente.

// Antes:
function criarPromise() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
}

// Depois: ES2024
const { promise, resolve, reject } = Promise.withResolvers();
setTimeout(() => resolve('sucesso!'), 1000);
promise.then(resultado => console.log(resultado)); // sucesso!

Os métodos .findLast() e .findLastIndex() que começaram em ES2023 agora têm suporte universal. O String.prototype.replaceAll() (já em ES2021, mas consolidado) é essencial para substituir todas as ocorrências sem regex global. O novo operador ??= (nullish coalescing assignment) atualiza variáveis apenas se forem null ou undefined.

// replaceAll
const texto = "gato gato gato";
console.log(texto.replaceAll('gato', 'cachorro')); 
// "cachorro cachorro cachorro"

// ??= (nullish coalescing assignment)
let config = null;
config ??= { tema: 'escuro', idioma: 'pt-BR' };
console.log(config); // { tema: 'escuro', idioma: 'pt-BR' }

let config2 = { tema: 'claro' };
config2 ??= { tema: 'escuro' };
console.log(config2); // { tema: 'claro' } - não foi alterado

Padrões Práticos: Integrando as Novidades

Na prática profissional, essas features se combinam para código mais expressivo. Um exemplo real: processar logs de API, agrupar por status, e retornar as últimas 3 respostas por grupo usando ES2023+2024.

const logs = [
  { timestamp: Date.now(), status: 200, mensagem: 'OK' },
  { timestamp: Date.now() - 1000, status: 500, mensagem: 'Erro' },
  { timestamp: Date.now() - 2000, status: 200, mensagem: 'OK' },
  { timestamp: Date.now() - 3000, status: 404, mensagem: 'Não encontrado' },
  { timestamp: Date.now() - 4000, status: 200, mensagem: 'OK' }
];

// Agrupar por status e pegar últimos 3 de cada grupo
const agrupado = Object.groupBy(logs, l => l.status);
const resumo = Object.entries(agrupado).map(([status, items]) => ({
  status,
  ultimos: items.toReversed().slice(0, 3)
}));

console.log(resumo);
// Mostra os 3 últimos logs de cada código de status

Conclusão

As novidades ES2022-2024 não são apenas açúcar sintático—elas resolvem problemas reais de forma elegante. Top-level await e campos privados melhoram a estrutura do código; Object.groupBy() e métodos de array imutáveis eliminam boilerplate; Promise.withResolvers() simplifica padrões async comuns. Dominar essas features torna você um desenvolvedor moderno e produtivo. Comece aplicando-as em seus projetos e note a redução de complexidade.

Referências


Artigos relacionados