Voltar para o Blog

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

Ola HaWkers, o ECMAScript 2025 foi oficialmente aprovado e traz uma serie de recursos que vao facilitar a vida de desenvolvedores JavaScript. Desde melhorias em expressoes regulares ate novos tipos de array para graficos e machine learning, essa atualizacao tem algo para todos.

Voce ja se perguntou como o JavaScript continua evoluindo ano apos ano? Vamos explorar cada novo recurso do ES2025 com exemplos praticos que voce pode comecar a usar hoje.

Visao Geral das Novidades

Antes de mergulhar nos detalhes, aqui esta um resumo do que o ECMAScript 2025 traz:

Principais adicoes:

  • Promise.try() - Execucao segura de funcoes sincronas
  • Float16Array - Novo TypedArray de meia precisao
  • Duplicate Named Capture Groups - Regex mais flexivel
  • RegExp.escape() - Escape automatico de caracteres especiais
  • Set methods - Operacoes de conjunto nativas
  • Iterator helpers - Metodos auxiliares para iteradores

💡 Contexto: O JavaScript recebe atualizacoes anuais desde 2015 (ES6), mantendo a linguagem moderna e competitiva.

Promise.try(): Tratamento Uniforme de Funcoes

Um dos recursos mais praticos do ES2025 e o Promise.try(), que resolve um problema comum: executar funcoes que podem ser sincronas ou assincronas.

O Problema Antigo

Antes, se voce tinha uma funcao que podia lancar erro sincronamente, precisava de tratamento especial:

// Problema: se getUser lanca erro sincrono, o catch nao pega
function fetchUserData(userId) {
  // Se userId for invalido, isso lanca erro ANTES da Promise
  const user = getUser(userId); // Pode lancar erro sincrono!
  return Promise.resolve(user)
    .then(user => processUser(user))
    .catch(err => handleError(err)); // Nao pega erros sincronos!
}

// Solucao antiga: envolver em try-catch ou Promise
function fetchUserDataSafe(userId) {
  return new Promise((resolve, reject) => {
    try {
      const user = getUser(userId);
      resolve(user);
    } catch (err) {
      reject(err);
    }
  }).then(user => processUser(user))
    .catch(err => handleError(err));
}

A Solucao com Promise.try()

Agora, tudo fica mais simples:

// ES2025: Promise.try resolve o problema elegantemente
function fetchUserData(userId) {
  return Promise.try(() => getUser(userId))
    .then(user => processUser(user))
    .catch(err => handleError(err));
}

// Funciona com funcoes async tambem
function fetchUserDataAsync(userId) {
  return Promise.try(async () => {
    const user = await getUser(userId);
    const profile = await getProfile(user.id);
    return { user, profile };
  })
    .then(data => processData(data))
    .catch(err => handleError(err));
}

// Exemplo pratico: validacao e fetch
function loadResource(resourceId) {
  return Promise.try(() => {
    // Validacao sincrona que pode lancar erro
    if (!isValidId(resourceId)) {
      throw new Error('ID invalido');
    }
    // Operacao assincrona
    return fetch(`/api/resources/${resourceId}`);
  })
    .then(response => response.json())
    .catch(err => {
      console.error('Erro ao carregar recurso:', err);
      return null;
    });
}

Float16Array: Precisao para Graficos e ML

O novo Float16Array adiciona suporte para numeros de ponto flutuante de 16 bits, essencial para graficos e machine learning.

Por Que 16 Bits?

Comparacao de precisao:

Tipo Bits Memoria Uso
Float16 16 2 bytes Graficos, ML
Float32 32 4 bytes Uso geral
Float64 64 8 bytes Alta precisao

Usando Float16Array

// Criando um Float16Array
const halfFloats = new Float16Array(4);
halfFloats[0] = 1.5;
halfFloats[1] = 2.25;
halfFloats[2] = 0.125;
halfFloats[3] = -3.75;

console.log(halfFloats); // Float16Array(4) [1.5, 2.25, 0.125, -3.75]

// Criando a partir de array existente
const values = [0.5, 1.0, 1.5, 2.0, 2.5];
const f16 = Float16Array.from(values);

// Util para WebGL e WebGPU
const vertexData = new Float16Array([
  // x, y, z, u, v
  -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,
]);

// Economia de memoria para ML
const weights = new Float16Array(1000000); // 2MB vs 4MB com Float32

Funcoes Auxiliares

// Novas funcoes Math para Float16
const f16Value = Math.f16round(3.14159); // Arredonda para precisao f16
console.log(f16Value); // 3.140625

// Util para shaders e GPU computing
function prepareGPUData(floatArray) {
  // Converte Float32 para Float16 para enviar a GPU
  const f16Data = Float16Array.from(floatArray);
  return f16Data.buffer;
}

// DataView tambem suporta Float16
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);

view.setFloat16(0, 1.5);           // Escreve Float16
view.setFloat16(2, 2.5, true);     // Little-endian

const value1 = view.getFloat16(0); // Le Float16
const value2 = view.getFloat16(2, true);

Duplicate Named Capture Groups

Uma limitacao frustrante de regex foi resolvida: agora voce pode usar o mesmo nome de grupo em diferentes partes de uma expressao regular.

O Problema Antigo

// Antes: isso era um erro de sintaxe
// const dateRegex = /(?<day>\d{2})-(?<month>\d{2})|(?<month>\d{2})\/(?<day>\d{2})/;
// SyntaxError: Duplicate capture group name

// Solucao antiga: nomes diferentes
const dateRegexOld = /(?<day1>\d{2})-(?<month1>\d{2})|(?<month2>\d{2})\/(?<day2>\d{2})/;
const match = '25-12'.match(dateRegexOld);
// Precisava verificar qual grupo matched
const day = match.groups.day1 || match.groups.day2;
const month = match.groups.month1 || match.groups.month2;

A Solucao ES2025

// ES2025: mesmo nome em alternativas diferentes
const dateRegex = /(?<day>\d{2})-(?<month>\d{2})|(?<month>\d{2})\/(?<day>\d{2})/;

// Formato DD-MM
const match1 = '25-12'.match(dateRegex);
console.log(match1.groups.day);   // "25"
console.log(match1.groups.month); // "12"

// Formato MM/DD
const match2 = '12/25'.match(dateRegex);
console.log(match2.groups.day);   // "25"
console.log(match2.groups.month); // "12"

// Exemplo mais complexo: multiplos formatos de data
const flexibleDate = /
  (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})|
  (?<day>\d{2})\/(?<month>\d{2})\/(?<year>\d{4})|
  (?<month>\d{2})-(?<day>\d{2})-(?<year>\d{4})
/x;

// Todos funcionam com os mesmos nomes de grupo
['2025-12-25', '25/12/2025', '12-25-2025'].forEach(date => {
  const m = date.match(flexibleDate);
  console.log(`${m.groups.year}-${m.groups.month}-${m.groups.day}`);
});

RegExp.escape(): Escape Automatico

Finalmente temos uma forma nativa de escapar strings para uso em expressoes regulares.

O Problema

// Antes: precisava criar funcao propria ou usar biblioteca
function escapeRegex(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// Ou arriscar bugs
const userInput = 'file.txt';
const regex = new RegExp(userInput); // Problema: . casa qualquer caractere!
'fileAtxt'.match(regex); // Match indesejado!

A Solucao Nativa

// ES2025: RegExp.escape()
const userInput = 'file.txt';
const escaped = RegExp.escape(userInput);
console.log(escaped); // "file\\.txt"

const regex = new RegExp(escaped);
'file.txt'.match(regex);  // Match correto
'fileAtxt'.match(regex);  // null - nao casa mais

// Util para busca de texto literal
function findExactText(text, searchTerm) {
  const escaped = RegExp.escape(searchTerm);
  const regex = new RegExp(escaped, 'gi');
  return text.match(regex);
}

// Funciona com qualquer caractere especial
const specialChars = '(hello) [world] {test} $100 ^start end$';
const safeRegex = new RegExp(RegExp.escape(specialChars));

// Exemplo pratico: highlight de texto
function highlightText(content, searchTerm) {
  const escaped = RegExp.escape(searchTerm);
  const regex = new RegExp(`(${escaped})`, 'gi');
  return content.replace(regex, '<mark>$1</mark>');
}

highlightText('Price: $99.99', '$99.99');
// "Price: <mark>$99.99</mark>"

Set Methods: Operacoes de Conjunto Nativas

O ES2025 adiciona metodos nativos para operacoes comuns de conjuntos.

Novos Metodos

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

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

// Intersecao: elementos em A E B
const intersection = setA.intersection(setB);
console.log([...intersection]); // [4, 5]

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

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

// Subconjunto: A esta contido em B?
const small = new Set([4, 5]);
console.log(small.isSubsetOf(setA)); // true
console.log(small.isSubsetOf(setB)); // true

// Superconjunto: A contem B?
console.log(setA.isSupersetOf(small)); // true

// Disjunto: A e B nao tem elementos em comum?
const setC = new Set([10, 11, 12]);
console.log(setA.isDisjointFrom(setC)); // true
console.log(setA.isDisjointFrom(setB)); // false

Exemplos Praticos

// Gerenciamento de permissoes
const userPermissions = new Set(['read', 'write', 'delete']);
const requiredPermissions = new Set(['read', 'write']);

const hasAccess = requiredPermissions.isSubsetOf(userPermissions);
console.log(hasAccess); // true

// Encontrar tags em comum entre posts
const post1Tags = new Set(['javascript', 'web', 'frontend']);
const post2Tags = new Set(['javascript', 'nodejs', 'backend']);

const commonTags = post1Tags.intersection(post2Tags);
console.log([...commonTags]); // ['javascript']

// Combinar listas de usuarios sem duplicatas
const team1 = new Set(['alice', 'bob', 'charlie']);
const team2 = new Set(['bob', 'diana', 'eve']);

const allMembers = team1.union(team2);
console.log([...allMembers]); // ['alice', 'bob', 'charlie', 'diana', 'eve']

Iterator Helpers: Metodos para Iteradores

Agora iteradores tem metodos auxiliares similares aos de arrays.

Metodos Disponiveis

// Criando um iterador
function* infiniteNumbers() {
  let n = 0;
  while (true) {
    yield n++;
  }
}

// take(): pegar N primeiros elementos
const first5 = infiniteNumbers().take(5);
console.log([...first5]); // [0, 1, 2, 3, 4]

// drop(): pular N primeiros elementos
const skip3take5 = infiniteNumbers().drop(3).take(5);
console.log([...skip3take5]); // [3, 4, 5, 6, 7]

// map(): transformar elementos
const doubled = infiniteNumbers()
  .take(5)
  .map(n => n * 2);
console.log([...doubled]); // [0, 2, 4, 6, 8]

// filter(): filtrar elementos
const evens = infiniteNumbers()
  .take(10)
  .filter(n => n % 2 === 0);
console.log([...evens]); // [0, 2, 4, 6, 8]

// flatMap(): map + flatten
function* pairs(n) {
  yield n;
  yield n * 10;
}

const flattened = [1, 2, 3].values()
  .flatMap(n => pairs(n));
console.log([...flattened]); // [1, 10, 2, 20, 3, 30]

Encadeamento Fluente

// Combinando metodos
const result = infiniteNumbers()
  .drop(10)           // Pula os 10 primeiros
  .filter(n => n % 3 === 0)  // Apenas multiplos de 3
  .map(n => n ** 2)   // Eleva ao quadrado
  .take(5);           // Pega 5 resultados

console.log([...result]); // [144, 225, 324, 441, 576]

// Exemplo pratico: processamento de dados
function* readLines(text) {
  for (const line of text.split('\n')) {
    yield line;
  }
}

const logData = `
2025-01-01 ERROR: Connection failed
2025-01-01 INFO: Server started
2025-01-02 ERROR: Timeout
2025-01-02 INFO: Request processed
2025-01-03 ERROR: Invalid input
`;

const errors = readLines(logData)
  .filter(line => line.includes('ERROR'))
  .map(line => line.split('ERROR:')[1]?.trim())
  .filter(msg => msg);

console.log([...errors]);
// ['Connection failed', 'Timeout', 'Invalid input']

Compatibilidade e Suporte

Antes de usar esses recursos em producao, verifique o suporte:

Status de Implementacao

Recurso Chrome Firefox Safari Node.js
Promise.try 128+ 132+ 18.2+ 22+
Float16Array 128+ Em dev 18.2+ 22+
Duplicate Groups 125+ 129+ 18+ 21+
RegExp.escape 130+ 134+ Em dev 23+
Set methods 122+ 127+ 17+ 22+
Iterator helpers 122+ 131+ 17+ 22+

Polyfills e Transpilacao

// Para ambientes que nao suportam, use core-js
import 'core-js/actual/promise/try';
import 'core-js/actual/set';
import 'core-js/actual/iterator';

// Ou configure babel com preset-env
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.25%, not dead',
      useBuiltIns: 'usage',
      corejs: 3
    }]
  ]
};

Conclusao

O ECMAScript 2025 traz melhorias praticas que resolvem problemas reais do dia a dia. Promise.try() simplifica tratamento de erros, Float16Array abre portas para graficos e ML, e os novos metodos de Set e Iterator tornam operacoes comuns mais elegantes.

O JavaScript continua evoluindo de forma consistente, adicionando recursos que antes exigiam bibliotecas externas ou codigo boilerplate. Manter-se atualizado com essas novidades e essencial para escrever codigo mais limpo e eficiente.

Se voce quer se aprofundar em JavaScript moderno, recomendo que de uma olhada em outro artigo: Descobrindo o Poder de Async/Await em JavaScript onde voce vai descobrir como dominar programacao assincrona.

Bora pra cima! 🦅

💻 Domine JavaScript de Verdade

O conhecimento que voce adquiriu neste artigo e so o comeco. Ha tecnicas, padroes e praticas que transformam desenvolvedores iniciantes em profissionais requisitados.

Invista no Seu Futuro

Preparei um material completo para voce dominar JavaScript:

Formas de pagamento:

  • 1x de R$9,90 sem juros
  • ou R$9,90 a vista

📖 Ver Conteudo Completo

Comentários (0)

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

Adicionar comentário