Voltar para o Blog

ECMAScript 2025: Os Novos Recursos do JavaScript Que Voce Precisa Conhecer

Ola HaWkers, mais um ano e mais uma atualizacao do ECMAScript foi oficialmente aprovada pelo TC39. O ECMAScript 2025 traz recursos que podem parecer incrementais a primeira vista, mas que resolvem problemas reais que desenvolvedores enfrentam no dia a dia.

Voce ja teve dificuldades com regex complexas ou precisou otimizar memoria em aplicacoes graficas? As novidades deste ano abordam exatamente esses cenarios.

O Que Mudou no ECMAScript 2025

O processo de evolucao do JavaScript segue um ciclo anual bem definido. Propostas passam por estagios (Stage 0 a Stage 4) antes de serem incorporadas ao padrao oficial. Em 2025, temos algumas adicoes interessantes que ja estao disponiveis nos principais navegadores e runtimes.

Principais Adicoes

Recursos aprovados em ES2025:

  1. Float16Array - Novo TypedArray para precisao de 16 bits
  2. Duplicate Named Capture Groups - Regex mais flexiveis
  3. Set Methods - Operacoes de conjunto nativas
  4. Promise.try - Tratamento unificado de erros
  5. RegExp.escape - Escape seguro de strings para regex
  6. Import Attributes - Metadados em imports

Float16Array: Otimizacao de Memoria Para Graficos e IA

O Float16Array e uma das adicoes mais significativas para quem trabalha com WebGL, WebGPU ou machine learning no browser.

Por Que Float16 Importa

Ate agora, tinhamos apenas Float32Array e Float64Array. O problema? Muitas aplicacoes graficas e de IA nao precisam de tanta precisao, e usar 32 ou 64 bits desperdicava memoria.

// Comparacao de tamanho em bytes para 1000 elementos
const float64 = new Float64Array(1000); // 8000 bytes
const float32 = new Float32Array(1000); // 4000 bytes
const float16 = new Float16Array(1000); // 2000 bytes - NOVO!

console.log('Float64:', float64.byteLength, 'bytes');
console.log('Float32:', float32.byteLength, 'bytes');
console.log('Float16:', float16.byteLength, 'bytes');
// Float16 usa 50% menos memoria que Float32!

Uso Pratico com WebGPU

// Criando buffer de vertices otimizado para WebGPU
const vertices = new Float16Array([
  // x, y, z, u, v - coordenadas e texturas
  -1.0, -1.0, 0.0, 0.0, 0.0,
   1.0, -1.0, 0.0, 1.0, 0.0,
   0.0,  1.0, 0.0, 0.5, 1.0,
]);

// Funcoes auxiliares para conversao
const value = 3.14159;
const f16Bits = Math.f16round(value); // Arredonda para Float16

// Verificar se o valor pode ser representado em Float16
function isFloat16Safe(num) {
  const rounded = Math.f16round(num);
  return Object.is(num, rounded) ||
         (Number.isNaN(num) && Number.isNaN(rounded));
}

console.log(isFloat16Safe(0.1));     // true
console.log(isFloat16Safe(65536));   // false (overflow)

DataView com Float16

const buffer = new ArrayBuffer(10);
const view = new DataView(buffer);

// Novos metodos do DataView
view.setFloat16(0, 3.14, true);  // little-endian
view.setFloat16(2, 2.71, false); // big-endian

const pi = view.getFloat16(0, true);
const e = view.getFloat16(2, false);

console.log(pi); // ~3.140625 (precisao de 16 bits)
console.log(e);  // ~2.710938

Duplicate Named Capture Groups

Este recurso resolve uma limitacao frustrante das regex em JavaScript: nao podiamos usar o mesmo nome em grupos de captura alternativos.

O Problema Anterior

// ANTES: Isso gerava erro de sintaxe!
// const dateRegex = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;
// SyntaxError: Duplicate capture group name

// Tinhamos que usar nomes diferentes
const dateRegexOld = /(?<year1>\d{4})-(?<month1>\d{2})|(?<month2>\d{2})\/(?<year2>\d{4})/;

A Solucao em ES2025

// AGORA: Funciona perfeitamente!
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;

// Parsing de diferentes formatos de data
const dates = [
  '2025-11-30',    // formato ISO
  '30/11/2025',    // formato brasileiro
];

dates.forEach(date => {
  const match = date.match(dateRegex);
  if (match) {
    console.log(`Ano: ${match.groups.year}, Mes: ${match.groups.month}`);
  }
});
// Ano: 2025, Mes: 11
// Ano: 2025, Mes: 11

Caso de Uso Real: Parser de Logs

// Parser flexivel para diferentes formatos de log
const logRegex = /
  (?:\[(?<level>INFO|WARN|ERROR)\])|
  (?:(?<level>info|warn|error):)
/xi;

const logs = [
  '[ERROR] Database connection failed',
  'warn: Memory usage high',
  '[INFO] Server started',
];

logs.forEach(log => {
  const match = log.match(logRegex);
  if (match) {
    const level = match.groups.level.toUpperCase();
    console.log(`Nivel: ${level}`);
  }
});

Set Methods: Operacoes de Conjunto Nativas

Finalmente temos metodos nativos para operacoes de conjunto que antes precisavamos implementar manualmente.

Novos Metodos Disponiveis

const setA = new Set([1, 2, 3, 4, 5]);
const setB = new Set([4, 5, 6, 7, 8]);

// Union - elementos em A ou B
const union = setA.union(setB);
console.log([...union]); // [1, 2, 3, 4, 5, 6, 7, 8]

// Intersection - elementos em A e B
const intersection = setA.intersection(setB);
console.log([...intersection]); // [4, 5]

// Difference - elementos em A mas nao em B
const difference = setA.difference(setB);
console.log([...difference]); // [1, 2, 3]

// Symmetric Difference - elementos em A ou B, mas nao em ambos
const symmetricDiff = setA.symmetricDifference(setB);
console.log([...symmetricDiff]); // [1, 2, 3, 6, 7, 8]

Metodos de Verificacao

const admins = new Set(['alice', 'bob']);
const users = new Set(['alice', 'bob', 'charlie', 'diana']);
const guests = new Set(['eve', 'frank']);

// isSubsetOf - A esta contido em B?
console.log(admins.isSubsetOf(users));     // true
console.log(users.isSubsetOf(admins));     // false

// isSupersetOf - A contem B?
console.log(users.isSupersetOf(admins));   // true

// isDisjointFrom - A e B nao tem elementos em comum?
console.log(admins.isDisjointFrom(guests)); // true
console.log(admins.isDisjointFrom(users));  // false

Aplicacao Pratica: Sistema de Permissoes

class PermissionManager {
  constructor() {
    this.roles = {
      admin: new Set(['read', 'write', 'delete', 'manage_users']),
      editor: new Set(['read', 'write']),
      viewer: new Set(['read']),
    };
  }

  hasAllPermissions(userPermissions, requiredPermissions) {
    return requiredPermissions.isSubsetOf(userPermissions);
  }

  getMissingPermissions(userPermissions, requiredPermissions) {
    return requiredPermissions.difference(userPermissions);
  }

  combineRoles(...roleNames) {
    return roleNames.reduce((combined, role) => {
      return combined.union(this.roles[role] || new Set());
    }, new Set());
  }
}

const pm = new PermissionManager();
const userPerms = pm.combineRoles('editor', 'viewer');
const required = new Set(['read', 'write', 'delete']);

console.log('Has all:', pm.hasAllPermissions(userPerms, required)); // false
console.log('Missing:', [...pm.getMissingPermissions(userPerms, required)]); // ['delete']

Promise.try: Tratamento Unificado de Erros

O Promise.try resolve um problema comum: quando voce tem uma funcao que pode ser sincrona ou assincrona e quer tratar erros de forma unificada.

O Problema

// ANTES: Codigo inconsistente
function processData(data) {
  // Se isso lancar erro sincrono, o catch nao pega!
  return validateSync(data)
    .then(validated => transform(validated))
    .catch(err => console.error(err));
}

// Solucao antiga (verbosa)
function processDataOld(data) {
  return new Promise(resolve => resolve(validateSync(data)))
    .then(validated => transform(validated))
    .catch(err => console.error(err));
}

A Solucao com Promise.try

// AGORA: Limpo e consistente
function processData(data) {
  return Promise.try(() => validateSync(data))
    .then(validated => transform(validated))
    .catch(err => console.error(err));
}

// Funciona com funcoes sync e async
const result1 = Promise.try(() => {
  return 42; // sincrono
});

const result2 = Promise.try(async () => {
  const response = await fetch('/api/data');
  return response.json(); // assincrono
});

// Erros sincronos sao capturados
const result3 = Promise.try(() => {
  throw new Error('Sync error');
}).catch(err => {
  console.log('Caught:', err.message); // Caught: Sync error
});

RegExp.escape: Escape Seguro de Strings

Quando voce precisa usar input do usuario em uma regex, escapar caracteres especiais era manual e propenso a erros.

// ANTES: Funcao manual (comum em projetos)
function escapeRegExpOld(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// AGORA: Metodo nativo
const userInput = 'Hello (World)? [Test]';
const escaped = RegExp.escape(userInput);
console.log(escaped); // Hello \(World\)\? \[Test\]

// Uso seguro em regex dinamica
function highlightText(text, searchTerm) {
  const safePattern = RegExp.escape(searchTerm);
  const regex = new RegExp(`(${safePattern})`, 'gi');
  return text.replace(regex, '<mark>$1</mark>');
}

const result = highlightText(
  'Price is $50 (special offer!)',
  '$50 (special'
);
// Price is <mark>$50 (special</mark> offer!)

Import Attributes: Metadados em Imports

Import Attributes permitem passar informacoes adicionais ao importar modulos, especialmente util para JSON e outros tipos de arquivos.

// Importando JSON com type assertion
import config from './config.json' with { type: 'json' };

// Import dinamico com atributos
const data = await import('./data.json', {
  with: { type: 'json' }
});

// Isso ajuda engines a otimizar e validar imports
// Tambem melhora a seguranca ao explicitar o tipo esperado

Compatibilidade e Adocao

Suporte nos Navegadores

Recurso Chrome Firefox Safari Node.js
Float16Array 127+ 129+ 18.2+ 22+
Duplicate Named Groups 125+ 128+ 18+ 22+
Set Methods 122+ 127+ 17+ 22+
Promise.try 128+ Em desenvolvimento 18+ 22+
RegExp.escape Em desenvolvimento Em desenvolvimento 18+ 22+

Usando Hoje com Transpiladores

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: { node: 'current' },
      shippedProposals: true,
    }],
  ],
};

Conclusao

O ECMAScript 2025 pode nao ter o impacto visual de adicoes como async/await ou optional chaining, mas cada recurso resolve problemas praticos. Float16Array vai beneficiar aplicacoes graficas e de IA, os Set Methods simplificam codigo que antes era verboso, e Promise.try padroniza algo que desenvolvedores implementavam de formas diferentes.

A evolucao incremental do JavaScript mostra a maturidade da linguagem. Nao precisamos de revolucoes a cada ano; melhorias pontuais e bem pensadas mantem a linguagem moderna sem quebrar compatibilidade.

Se voce quer acompanhar mais novidades sobre JavaScript e desenvolvimento web, recomendo dar uma olhada no artigo sobre Svelte 5 e Runes onde exploramos outra inovacao que esta transformando como escrevemos codigo reativo.

Bora pra cima! 🦅

📚 Quer Aprofundar Seus Conhecimentos em JavaScript?

Este artigo cobriu as novidades do ECMAScript 2025, mas ha muito mais para explorar no ecossistema JavaScript.

Desenvolvedores que dominam os fundamentos e acompanham a evolucao da linguagem se destacam no mercado.

Material de Estudo Completo

Se voce quer dominar JavaScript do basico ao avancado, preparei um guia completo:

Opcoes de investimento:

  • 1x de R$9,90 no cartao
  • ou R$9,90 a vista

👉 Conhecer o Guia JavaScript

💡 Material atualizado com as melhores praticas do mercado

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário