ECMAScript 2025: As Novas Features do JavaScript Que Voce Precisa Conhecer
Olá HaWkers, o ECMAScript 2025 trouxe uma das atualizações mais substanciais dos últimos anos para o JavaScript. Com novos Iterator helpers, métodos de Set, importação direta de JSON e melhorias em Promises, a linguagem continua evoluindo para atender às necessidades dos desenvolvedores modernos.
Vamos explorar cada uma dessas novidades com exemplos práticos que você pode começar a usar hoje mesmo.
Iterator Helpers: A Grande Estrela
A adição mais aguardada do ES2025 são os Iterator helpers. Finalmente, podemos usar métodos como map, filter e reduce diretamente em iteradores, sem precisar converter para arrays.
Por Que Isso Importa
Antes, trabalhar com iteradores exigia conversão constante:
// Antes do ES2025 - Ineficiente para grandes conjuntos
function* gerarNumeros(limite) {
for (let i = 0; i < limite; i++) {
yield i;
}
}
// Precisava converter para array primeiro
const numeros = [...gerarNumeros(1000000)];
const pares = numeros.filter(n => n % 2 === 0);
const dobrados = pares.map(n => n * 2);
const soma = dobrados.reduce((acc, n) => acc + n, 0);
// Problema: Cria 3 arrays intermediarios na memoriaAgora com Iterator helpers:
// ES2025 - Lazy evaluation, sem arrays intermediarios
function* gerarNumeros(limite) {
for (let i = 0; i < limite; i++) {
yield i;
}
}
const resultado = gerarNumeros(1000000)
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((acc, n) => acc + n, 0);
// Processa item por item, sem criar arrays intermediarios
console.log(resultado);Metodos Disponiveis
O objeto Iterator agora possui métodos funcionais nativos:
// map - Transforma cada elemento
const iterator = [1, 2, 3].values();
const dobrados = iterator.map(x => x * 2);
console.log([...dobrados]); // [2, 4, 6]
// filter - Filtra elementos
const numeros = [1, 2, 3, 4, 5].values();
const pares = numeros.filter(x => x % 2 === 0);
console.log([...pares]); // [2, 4]
// take - Pega os primeiros N elementos
const infinito = function* () {
let i = 0;
while (true) yield i++;
}();
const primeiros = infinito.take(5);
console.log([...primeiros]); // [0, 1, 2, 3, 4]
// drop - Pula os primeiros N elementos
const lista = [1, 2, 3, 4, 5].values();
const semPrimeiros = lista.drop(2);
console.log([...semPrimeiros]); // [3, 4, 5]
// flatMap - Map + flatten
const aninhado = [[1, 2], [3, 4]].values();
const achatado = aninhado.flatMap(arr => arr.values());
console.log([...achatado]); // [1, 2, 3, 4]Caso de Uso Real: Processamento de Dados
// Processando linhas de um arquivo grande com lazy evaluation
async function* lerLinhas(arquivo) {
const reader = arquivo.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const linhas = buffer.split('\n');
buffer = linhas.pop(); // Guarda linha incompleta
for (const linha of linhas) {
yield linha;
}
}
if (buffer) yield buffer;
}
// Usando iterator helpers para processar
const csvProcessado = lerLinhas(arquivoGrande)
.filter(linha => linha.trim() !== '')
.filter(linha => !linha.startsWith('#'))
.map(linha => linha.split(','))
.filter(campos => campos.length === 4)
.map(([nome, email, idade, cidade]) => ({
nome: nome.trim(),
email: email.trim(),
idade: parseInt(idade),
cidade: cidade.trim()
}))
.filter(pessoa => pessoa.idade >= 18);
// Apenas 100 registros, sem carregar arquivo inteiro
const primeiros100 = csvProcessado.take(100);Novos Metodos de Set
Os Sets JavaScript finalmente receberam métodos que já existiam em outras linguagens há décadas.
Operacoes de Conjunto
const setA = new Set([1, 2, 3, 4, 5]);
const setB = new Set([4, 5, 6, 7, 8]);
// union - Todos os elementos de ambos os conjuntos
const uniao = setA.union(setB);
console.log([...uniao]); // [1, 2, 3, 4, 5, 6, 7, 8]
// intersection - Elementos comuns
const intersecao = setA.intersection(setB);
console.log([...intersecao]); // [4, 5]
// difference - Elementos em A que nao estao em B
const diferenca = setA.difference(setB);
console.log([...diferenca]); // [1, 2, 3]
// symmetricDifference - Elementos exclusivos de cada conjunto
const diferencaSimetrica = setA.symmetricDifference(setB);
console.log([...diferencaSimetrica]); // [1, 2, 3, 6, 7, 8]
// isSubsetOf - Verifica se A esta contido em B
const subset = new Set([4, 5]);
console.log(subset.isSubsetOf(setA)); // true
console.log(subset.isSubsetOf(setB)); // true
// isSupersetOf - Verifica se A contem B
console.log(setA.isSupersetOf(subset)); // true
// isDisjointFrom - Verifica se nao ha elementos comuns
const setC = new Set([10, 11, 12]);
console.log(setA.isDisjointFrom(setC)); // true
console.log(setA.isDisjointFrom(setB)); // falseAplicacao Pratica: Sistema de Permissoes
class SistemaPermissoes {
constructor() {
this.roles = new Map();
}
definirRole(nome, permissoes) {
this.roles.set(nome, new Set(permissoes));
}
permissoesUsuario(rolesUsuario) {
return rolesUsuario.reduce((acc, role) => {
const permissoesRole = this.roles.get(role) || new Set();
return acc.union(permissoesRole);
}, new Set());
}
verificarAcesso(rolesUsuario, permissoesNecessarias) {
const permissoesUsuario = this.permissoesUsuario(rolesUsuario);
const necessarias = new Set(permissoesNecessarias);
// Verifica se usuario tem todas as permissoes necessarias
return necessarias.isSubsetOf(permissoesUsuario);
}
permissoesFaltantes(rolesUsuario, permissoesNecessarias) {
const permissoesUsuario = this.permissoesUsuario(rolesUsuario);
const necessarias = new Set(permissoesNecessarias);
// Retorna permissoes que o usuario nao tem
return necessarias.difference(permissoesUsuario);
}
}
// Uso
const sistema = new SistemaPermissoes();
sistema.definirRole('admin', ['criar', 'ler', 'atualizar', 'deletar', 'gerenciar_usuarios']);
sistema.definirRole('editor', ['criar', 'ler', 'atualizar']);
sistema.definirRole('leitor', ['ler']);
const usuario = ['editor', 'leitor'];
const permissoesNecessarias = ['criar', 'deletar'];
console.log(sistema.verificarAcesso(usuario, permissoesNecessarias)); // false
console.log([...sistema.permissoesFaltantes(usuario, permissoesNecessarias)]); // ['deletar']Import JSON Diretamente
Agora podemos importar arquivos JSON diretamente como módulos ES, sem necessidade de fetch ou require.
// config.json
// {
// "apiUrl": "https://api.exemplo.com",
// "timeout": 5000,
// "maxRetries": 3
// }
// Antes - Precisava de fetch ou fs
// const config = await fetch('./config.json').then(r => r.json());
// ES2025 - Import direto com assertion
import config from './config.json' with { type: 'json' };
console.log(config.apiUrl); // https://api.exemplo.com
console.log(config.timeout); // 5000Casos de Uso
// Importar dados estaticos
import traducoes from './lang/pt-BR.json' with { type: 'json' };
import rotas from './routes.json' with { type: 'json' };
import schema from './validation-schema.json' with { type: 'json' };
// Dynamic import tambem funciona
const locale = 'en-US';
const mensagens = await import(`./lang/${locale}.json`, {
with: { type: 'json' }
});Promise.try: Simplificando Cadeias de Promises
O novo método Promise.try permite iniciar uma cadeia de Promises de forma mais limpa, tratando tanto funções síncronas quanto assíncronas.
// Antes - Precisava de workarounds
function processarDados(dados) {
// Pode lancar excecao sincrona
const validados = validarDados(dados);
// Pode retornar Promise
return salvarNoBanco(validados);
}
// Workaround antigo
Promise.resolve()
.then(() => processarDados(dados))
.then(resultado => console.log(resultado))
.catch(erro => console.error(erro));
// ES2025 - Mais limpo
Promise.try(() => processarDados(dados))
.then(resultado => console.log(resultado))
.catch(erro => console.error(erro));Por Que Promise.try e Util
// Funcao que pode ser sincrona ou assincrona
function buscarUsuario(id) {
// Validacao sincrona pode lancar erro
if (!id || typeof id !== 'number') {
throw new Error('ID invalido');
}
// Cache sincrono
if (cache.has(id)) {
return cache.get(id); // Retorno sincrono
}
// Busca assincrona
return fetch(`/api/users/${id}`).then(r => r.json());
}
// Promise.try trata ambos os casos uniformemente
Promise.try(() => buscarUsuario(userId))
.then(usuario => renderizar(usuario))
.catch(erro => mostrarErro(erro));
// Equivalente a:
// new Promise(resolve => resolve(buscarUsuario(userId)))
// .then(...)
// .catch(...);Float16Array: Novo Typed Array
Para aplicações de machine learning e processamento de dados que precisam de eficiência de memória, o novo Float16Array oferece números de ponto flutuante de 16 bits.
// Float16Array usa metade da memoria de Float32Array
const dados16 = new Float16Array([1.5, 2.5, 3.5, 4.5]);
const dados32 = new Float32Array([1.5, 2.5, 3.5, 4.5]);
console.log(dados16.byteLength); // 8 bytes
console.log(dados32.byteLength); // 16 bytes
// Util para ML onde precisao total nao e necessaria
function criarTensorEficiente(dimensoes, valores) {
const total = dimensoes.reduce((a, b) => a * b, 1);
const dados = new Float16Array(total);
for (let i = 0; i < valores.length; i++) {
dados[i] = valores[i];
}
return {
shape: dimensoes,
data: dados,
dtype: 'float16'
};
}
const tensor = criarTensorEficiente([2, 3], [1, 2, 3, 4, 5, 6]);Melhorias em Regular Expressions
O ES2025 também trouxe melhorias para expressões regulares, incluindo o modificador de flag inline.
// Modifier flag inline - Ativa/desativa flags em partes da regex
const regex = /(?i:hello) world/;
// (?i:...) torna apenas "hello" case-insensitive
console.log(regex.test('HELLO world')); // true
console.log(regex.test('hello WORLD')); // false (world precisa ser minusculo)
// Util para padroes complexos
const emailRegex = /(?i:[a-z0-9._%+-]+)@(?i:[a-z0-9.-]+)\.(?i:[a-z]{2,})/;Suporte nos Navegadores
A maioria das features do ES2025 já está disponível nos navegadores modernos:
Iterator Helpers:
- Chrome 122+
- Firefox 131+
- Safari 17.4+
Set Methods:
- Chrome 122+
- Firefox 127+
- Safari 17+
JSON Modules:
- Chrome 123+
- Firefox 135+
- Safari 17.2+
Promise.try:
- Chrome 128+
- Firefox 132+
- Safari 18+
Para projetos que precisam suportar navegadores mais antigos, utilize transpiladores como Babel com os plugins apropriados.
Migrando Seu Codigo
Aqui está um checklist para começar a usar as novas features:
1. Atualize suas ferramentas:
npm update typescript @babel/core @babel/preset-env2. Configure o target do TypeScript:
{
"compilerOptions": {
"target": "ES2025",
"lib": ["ES2025", "DOM"]
}
}3. Adicione polyfills se necessário:
npm install core-js@latest// Importe apenas os polyfills necessarios
import 'core-js/actual/iterator';
import 'core-js/actual/set';
import 'core-js/actual/promise/try';O ECMAScript 2025 representa um passo significativo na evolução do JavaScript, trazendo features que tornam o código mais expressivo e eficiente. Se você quer aprofundar seus conhecimentos em JavaScript moderno, recomendo dar uma olhada no artigo sobre Web Workers: Performance com Threads onde você aprenderá técnicas avançadas de otimização.

