O que mudou no JavaScript em 2025
O JavaScript é uma das linguagens mais usadas do mundo e não para de crescer. A cada ano o TC39 - comité responsável pela evolução da linguagem - aprova novas propostas que chegam aos navegadores e ao Node.js. Em 2025 chegaram funcionalidades que os devs pediam há anos.
Diferente de outras linguagens, o JavaScript evolui de forma incremental. Cada proposta passa por estágios antes de ser oficialmente aprovada: do estágio 0 (ideia) até o estágio 4 (pronto para o padrão). Quando chega ao estágio 4, entra na especificação do ECMAScript daquele ano.
Neste post você vai ver as 7 funcionalidades mais relevantes aprovadas recentemente, com exemplos práticos de como usar cada uma no seu código hoje.
Como funciona a evolução do JavaScript
O TC39 é um grupo de engenheiros de empresas como Google, Mozilla, Apple, Microsoft e Meta que se reúne regularmente para discutir e aprovar mudanças na linguagem. Cada proposta passa por 5 estágios numerados de 0 a 4.
Estágio 4 significa que a proposta foi implementada em pelo menos dois navegadores ou ambientes e que os testes de conformidade passaram. A partir daí ela entra oficialmente no ECMAScript - por exemplo, ES2025 ou ES2026.
Você pode acompanhar o status de todas as propostas no repositório oficial do TC39 no GitHub. É uma leitura interessante para entender o futuro da linguagem antes que chegue ao seu compilador.
As 7 novas funcionalidades
1. Promise.try() - Permite iniciar uma cadeia de Promises a partir de uma função síncrona ou assíncrona sem precisar de um wrapper manual. Se a função lançar um erro síncrono, ele é convertido em uma Promise rejeitada automaticamente. Muito útil para evitar blocos try/catch misturados com .catch().
2. Array.fromAsync() - Cria um array a partir de um iterável ou iterável assíncrono. Antes você precisava de um loop for await...of para isso. Agora é uma linha: const items = await Array.fromAsync(asyncIterable).
3. Object.groupBy() e Map.groupBy() - Agrupa elementos de um iterável por uma chave retornada pelo callback. Substitui o clássico reduce que todo dev escrevia para agrupar arrays de objetos. Object.groupBy(users, u => u.role) retorna um objeto com chaves por papel.
4. Set com operações matemáticas - O objeto Set agora tem métodos como .union(), .intersection(), .difference() e .symmetricDifference(). Operações que você fazia manualmente com filter e has agora têm uma API nativa clara e legível.
5. Iterator Helpers - Métodos como .map(), .filter(), .take() e .drop() diretamente em iteradores, sem precisar converter para array primeiro. Útil para processar grandes datasets sem alocar memória desnecessária.
6. Regex com flag /v (unicodeSets) - A nova flag /v para expressões regulares permite classes de caracteres mais expressivas, propriedades de strings Unicode e operações de conjunto dentro de []. Melhora muito o trabalho com texto multilingue.
7. Promise.withResolvers() - Retorna um objeto com a Promise e suas funções resolve e reject separadas. Substitui o padrão verbose de criar uma Promise e guardar referência às funções externas. const { promise, resolve, reject } = Promise.withResolvers().
Como começar a usar hoje
A maioria dessas funcionalidades já está disponível nos navegadores modernos (Chrome 124+, Firefox 127+, Safari 17.4+) e no Node.js 22+. Se você usa TypeScript, verifique se seu tsconfig.json aponta para lib: ES2025 ou superior.
Para verificar o suporte de cada feature, o site caniuse.com e o MDN Web Docs têm tabelas de compatibilidade atualizadas. Para Node.js, a tabela de compatibilidade em node.green mostra quais versões suportam cada proposta.
Se você ainda não pode atualizar o ambiente, o Babel com os plugins corretos consegue transpilar a maioria dessas funcionalidades para versões mais antigas do JavaScript. Adicione os presets do Babel no seu projeto e configure o target de ambiente desejado.
Exemplo prático com as novas features
Imagine que você tem uma lista de pedidos e precisa agrupá-los por status. Antes você usaria um reduce com muito boilerplate. Com as novas features:
const pedidosPorStatus = Object.groupBy(pedidos, p => p.status);
Pronto. Um objeto com chaves pendente, aprovado, cancelado contendo arrays de pedidos. Sem reduce, sem acumuladores manuais, sem bugs de chave inexistente.
Para trabalhar com múltiplos usuários ativos e inativos como Sets: const ativos = new Set(usuariosAtivos); const inativos = new Set(usuariosInativos); const todos = ativos.union(inativos);. Muito mais legível do que o código anterior com filter e includes.
Comparação com alternativas e polyfills
Antes dessas funcionalidades nativas, a comunidade usava bibliotecas como Lodash para groupBy, Ramda para operações funcionais e implementações manuais de Set operations. Agora você tem essas coisas no JavaScript puro.
A vantagem do nativo é óbvia: sem dependência externa, sem bundle maior, sem risco de quebrar com atualizações de pacotes. O código fica mais legível para quem entra no projeto depois, pois são APIs padrão documentadas no MDN.
O Lodash ainda faz sentido para projetos legados ou quando você precisa de funcionalidades que ainda não têm equivalente nativo. Mas para novos projetos, vale a pena usar as APIs nativas sempre que possível.
Pontos positivos e limitações
O grande ponto positivo é que essas funcionalidades chegaram de forma retrocompatível. Nenhum código antigo quebra. Você simplesmente começa a usar as novas APIs onde fizer sentido.
A limitação principal é o suporte em ambientes mais antigos. Se você precisa suportar Node.js 18 ou navegadores de 2023, algumas dessas features não estarão disponíveis. Mas com Babel ou com polyfills pontuais do MDN, você consegue cobrir esses casos.
Outra limitação é a curva de aprendizado coletiva. Em times grandes, parte dos devs pode não conhecer as novas APIs, o que pode gerar inconsistências no código. Vale a pena fazer uma sessão rápida de onboarding mostrando as novidades para o time.
Casos de uso reais
Dev backend com Node.js 22+: usa Promise.try() para encapsular funções síncronas que podem lançar erros e mantém toda a cadeia de erros em Promises, sem misturar try/catch com .catch().
Dev frontend com React ou Vue: usa Object.groupBy() para agrupar itens de uma lista por categoria antes de renderizar, substituindo reducers verbosos em componentes de listagem.
Dev que trabalha com dados: usa Iterator Helpers para processar grandes arrays sem criar cópias intermediárias, reduzindo uso de memória em operações de filter + map encadeadas.
Dev que trabalha com permissões: usa Set.intersection() e Set.difference() para calcular quais permissões um usuário tem, quais faltam e quais são exclusivas de um grupo.
Dicas e boas práticas
Sempre verifique o suporte antes de usar em produção. O MDN tem uma tabela de compatibilidade no final de cada página de documentação - olhe antes de commitar.
Ao migrar código com Lodash para nativo, faça uma migration incremental. Não troque tudo de uma vez. Comece pelos arquivos mais simples e vá testando. Isso evita regressões inesperadas.
Configure o ESLint com as regras corretas para ES2025 no seu projeto. Sem isso, o linter pode reclamar das novas sintaxes ou você pode acabar usando versões de polyfill quando o nativo já está disponível.
Vale a pena aprender agora?
Sim, sem dúvida. O JavaScript de 2025 é mais expressivo, mais seguro e mais fácil de ler do que o de 5 anos atrás. Aprender essas funcionalidades coloca você na frente em revisões de código e em entrevistas técnicas.
O melhor caminho é ler a documentação no MDN de cada uma das features, experimentar no console do navegador e depois encontrar um lugar no seu projeto atual para aplicar. Aprendizado prático é sempre mais rápido do que só ler.
Se quiser ir mais fundo, o repositório do TC39 no GitHub tem todas as propostas com exemplos detalhados. Vale marcar como favorito e visitar de tempos em tempos para ver o que está chegando nos próximos ciclos.
Comentários
Deixar um comentárioVocê precisa ter uma conta no CuritibaBlog para comentar.