JavaScript ES2024: Novidades que vão mudar sua forma de programar
O JavaScript continua evoluindo rapidamente. O ES2024 trouxe funcionalidades incríveis que vão transformar a forma como escrevemos código. Vamos explorar as principais novidades.
1. Array grouping
Agrupe elementos de array de forma nativa:
const products = [
{ name: 'iPhone', category: 'electronics', price: 999 },
{ name: 'Shirt', category: 'clothing', price: 29 },
{ name: 'Laptop', category: 'electronics', price: 1299 },
{ name: 'Jeans', category: 'clothing', price: 79 }
];
// Agrupar por categoria
const groupedByCategory = products.groupBy(item => item.category);
console.log(groupedByCategory);
// {
// electronics: [
// { name: 'iPhone', category: 'electronics', price: 999 },
// { name: 'Laptop', category: 'electronics', price: 1299 }
// ],
// clothing: [
// { name: 'Shirt', category: 'clothing', price: 29 },
// { name: 'Jeans', category: 'clothing', price: 79 }
// ]
// }
// Agrupar por faixa de preço
const groupedByPrice = products.groupBy(item =>
item.price > 100 ? 'expensive' : 'affordable'
);
2. Promise.withResolvers()
Criar promises com resolvers externos:
// Antes
function createDeferredPromise() {
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}
// Agora - ES2024
const { promise, resolve, reject } = Promise.withResolvers();
// Uso prático
class EventualValue {
constructor() {
this.#deferred = Promise.withResolvers();
}
get value() {
return this.#deferred.promise;
}
setValue(value) {
this.#deferred.resolve(value);
}
setError(error) {
this.#deferred.reject(error);
}
}
const eventualData = new EventualValue();
// Em algum lugar do código
setTimeout(() => {
eventualData.setValue('Dados carregados!');
}, 2000);
// Em outro lugar
eventualData.value.then(data => console.log(data));
3. Temporal API (Preview)
Nova API para manipulação de datas:
// Dates mais precisas e timezone-aware
const now = Temporal.Now.plainDateTimeISO();
const birthday = Temporal.PlainDate.from('1990-05-15');
// Cálculos de data mais intuitivos
const age = now.toPlainDate().since(birthday, { unit: 'years' });
console.log(`Idade: ${age.years} anos`);
// Trabalhando com timezones
const meeting = Temporal.ZonedDateTime.from({
year: 2024,
month: 12,
day: 25,
hour: 10,
timeZone: 'America/Sao_Paulo'
});
const meetingInTokyo = meeting.withTimeZone('Asia/Tokyo');
console.log(meetingInTokyo.toString());
4. String.dedent
Remove indentação de template strings:
function generateHTML(title, content) {
return String.dedent`
<article>
<h1>${title}</h1>
<div class="content">
${content}
</div>
</article>
`;
}
const html = generateHTML('Meu Artigo', 'Conteúdo do artigo...');
// Retorna HTML sem indentação extra
5. Array.fromAsync()
Criar arrays de fontes assíncronas:
// Processar streams assíncronos
async function* fetchUserData() {
const userIds = [1, 2, 3, 4, 5];
for (const id of userIds) {
const response = await fetch(`/api/users/${id}`);
const user = await response.json();
yield user;
}
}
// Converter para array
const users = await Array.fromAsync(fetchUserData());
console.log(users); // Array com todos os usuários
// Com transformação
const userNames = await Array.fromAsync(
fetchUserData(),
user => user.name.toUpperCase()
);
6. Set methods
Novos métodos para Set:
const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
// Interseção
const intersection = set1.intersection(set2);
console.log(intersection); // Set {3, 4}
// União
const union = set1.union(set2);
console.log(union); // Set {1, 2, 3, 4, 5, 6}
// Diferença
const difference = set1.difference(set2);
console.log(difference); // Set {1, 2}
// Diferença simétrica
const symmetricDifference = set1.symmetricDifference(set2);
console.log(symmetricDifference); // Set {1, 2, 5, 6}
// Verificar se é subconjunto
const subset = new Set([1, 2]);
console.log(subset.isSubsetOf(set1)); // true
// Verificar se é superconjunto
console.log(set1.isSupersetOf(subset)); // true
// Verificar se são disjuntos
const disjoint = new Set([7, 8]);
console.log(set1.isDisjointFrom(disjoint)); // true
7. RegExp v flag
Nova flag para expressões regulares mais poderosas:
// Suporte a propriedades Unicode
const emojiRegex = /\p{Emoji}/v;
console.log(emojiRegex.test('😀')); // true
// Operações de conjunto em caracteres
const asciiLetters = /[a-zA-Z]/v;
const digits = /[0-9]/v;
// Intersections, unions, subtractions
const alphanumeric = /[\p{Letter}&&\p{ASCII}]/v;
const nonDigits = /[^\p{Number}]/v;
8. Import attributes
Importar módulos com metadados:
// Importar JSON
import config from './config.json' with { type: 'json' };
// Importar CSS (em alguns ambientes)
import styles from './styles.css' with { type: 'css' };
// Importar WebAssembly
import wasmModule from './module.wasm' with { type: 'webassembly' };
// Verificar tipo durante import
if (import.meta.resolve) {
const moduleUrl = import.meta.resolve('./module.js');
const module = await import(moduleUrl, {
with: { type: 'module' }
});
}
9. Decorator support (Stage 3)
Decorators nativos no JavaScript:
// Decorator de classe
@logged
class UserService {
@cache(60000) // Cache por 1 minuto
async getUser(id) {
return await fetch(`/api/users/${id}`).then(r => r.json());
}
@validate
createUser(userData) {
// Implementação
}
}
// Implementação dos decorators
function logged(target) {
return class extends target {
constructor(...args) {
super(...args);
console.log(`${target.name} instance created`);
}
};
}
function cache(duration) {
return function(target, propertyKey, descriptor) {
const originalMethod = descriptor.value;
const cache = new Map();
descriptor.value = function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
const cached = cache.get(key);
if (Date.now() - cached.timestamp < duration) {
return cached.value;
}
}
const result = originalMethod.apply(this, args);
cache.set(key, { value: result, timestamp: Date.now() });
return result;
};
};
}
10. Pipeline operator (Preview)
Composição de funções mais legível:
// Sem pipeline
const result = Math.round(Math.abs(Math.sqrt(16)));
// Com pipeline operator
const result = 16
|> Math.sqrt
|> Math.abs
|> Math.round;
// Uso mais complexo
const processUserData = (userData) =>
userData
|> validateUser
|> normalizeData
|> enrichWithMetadata
|> saveToDatabase;
// Com arrow functions
const users = await fetch('/api/users')
|> (response => response.json())
|> (data => data.filter(user => user.active))
|> (users => users.map(user => ({ ...user, processed: true })));
Casos de uso práticos
Data processing pipeline
const processAnalytics = (rawData) =>
rawData
|> (data => data.filter(item => item.valid))
|> (data => data.groupBy(item => item.category))
|> (grouped => Object.entries(grouped))
|> (entries => entries.map(([category, items]) => ({
category,
count: items.length,
revenue: items.reduce((sum, item) => sum + item.revenue, 0)
})))
|> (results => results.sort((a, b) => b.revenue - a.revenue));
Form validation
@validateOnSubmit
class ContactForm {
@required
@email
email = '';
@required
@minLength(3)
name = '';
@required
@minLength(10)
message = '';
}
Conclusão
O ES2024 continua tornando o JavaScript mais expressivo e poderoso. Essas funcionalidades vão gradualmente sendo implementadas pelos navegadores e engines, então fique atento ao suporte antes de usar em produção.
As novidades mostram que o JavaScript está evoluindo para ser mais funcional, mais expressivo e mais adequado para aplicações modernas complexas.

Comentários
0 ComentáriosSeja o primeiro a comentar neste artigo.