ECMAScript 2025 : Les Nouvelles Fonctionnalités JavaScript Que Vous Devez Connaître
Salut HaWkers, une nouvelle année et une nouvelle mise à jour d'ECMAScript a été officiellement approuvée par le TC39. ECMAScript 2025 apporte des fonctionnalités qui peuvent sembler incrémentales à première vue, mais qui résolvent des problèmes réels que les développeurs rencontrent au quotidien.
Avez-vous déjà eu des difficultés avec des regex complexes ou eu besoin d'optimiser la mémoire dans des applications graphiques ? Les nouveautés de cette année abordent exactement ces scénarios.
Ce Qui a Changé dans ECMAScript 2025
Le processus d'évolution de JavaScript suit un cycle annuel bien défini. Les propositions passent par des étapes (Stage 0 à Stage 4) avant d'être incorporées au standard officiel. En 2025, nous avons quelques ajouts intéressants qui sont déjà disponibles dans les principaux navigateurs et runtimes.
Principales Additions
Fonctionnalités approuvées en ES2025 :
- Float16Array - Nouveau TypedArray pour la précision 16 bits
- Duplicate Named Capture Groups - Regex plus flexibles
- Set Methods - Opérations d'ensemble natives
- Promise.try - Traitement unifié des erreurs
- RegExp.escape - Échappement sécurisé de chaînes pour regex
- Import Attributes - Métadonnées dans les imports
Float16Array : Optimisation Mémoire Pour Graphiques et IA
Le Float16Array est l'une des additions les plus significatives pour ceux qui travaillent avec WebGL, WebGPU ou machine learning dans le navigateur.
Pourquoi Float16 Importe
Jusqu'à présent, nous n'avions que Float32Array et Float64Array. Le problème ? Beaucoup d'applications graphiques et d'IA n'ont pas besoin d'autant de précision, et utiliser 32 ou 64 bits gaspillait de la mémoire.
// Comparaison de taille en bytes pour 1000 éléments
const float64 = new Float64Array(1000); // 8000 bytes
const float32 = new Float32Array(1000); // 4000 bytes
const float16 = new Float16Array(1000); // 2000 bytes - NOUVEAU !
console.log('Float64:', float64.byteLength, 'bytes');
console.log('Float32:', float32.byteLength, 'bytes');
console.log('Float16:', float16.byteLength, 'bytes');
// Float16 utilise 50% moins de mémoire que Float32 !Usage Pratique avec WebGPU
// Création d'un buffer de vertices optimisé pour WebGPU
const vertices = new Float16Array([
// x, y, z, u, v - coordonnées et textures
-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,
]);
// Fonctions auxiliaires pour la conversion
const value = 3.14159;
const f16Bits = Math.f16round(value); // Arrondit à Float16
// Vérifier si la valeur peut être représentée en 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 avec Float16
const buffer = new ArrayBuffer(10);
const view = new DataView(buffer);
// Nouvelles méthodes du 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 (précision de 16 bits)
console.log(e); // ~2.710938
Duplicate Named Capture Groups
Cette fonctionnalité résout une limitation frustrante des regex en JavaScript : nous ne pouvions pas utiliser le même nom dans des groupes de capture alternatifs.
Le Problème Précédent
// AVANT : Ceci générait une erreur de syntaxe !
// const dateRegex = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;
// SyntaxError: Duplicate capture group name
// Nous devions utiliser des noms différents
const dateRegexOld = /(?<year1>\d{4})-(?<month1>\d{2})|(?<month2>\d{2})\/(?<year2>\d{4})/;La Solution en ES2025
// MAINTENANT : Fonctionne parfaitement !
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;
// Parsing de différents formats de date
const dates = [
'2025-11-30', // format ISO
'30/11/2025', // format français
];
dates.forEach(date => {
const match = date.match(dateRegex);
if (match) {
console.log(`Année : ${match.groups.year}, Mois : ${match.groups.month}`);
}
});
// Année : 2025, Mois : 11
// Année : 2025, Mois : 11Cas d'Usage Réel : Parser de Logs
// Parser flexible pour différents formats 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(`Niveau : ${level}`);
}
});
Set Methods : Opérations d'Ensemble Natives
Nous avons enfin des méthodes natives pour les opérations d'ensemble que nous devions auparavant implémenter manuellement.
Nouvelles Méthodes Disponibles
const setA = new Set([1, 2, 3, 4, 5]);
const setB = new Set([4, 5, 6, 7, 8]);
// Union - éléments dans A ou B
const union = setA.union(setB);
console.log([...union]); // [1, 2, 3, 4, 5, 6, 7, 8]
// Intersection - éléments dans A et B
const intersection = setA.intersection(setB);
console.log([...intersection]); // [4, 5]
// Difference - éléments dans A mais pas dans B
const difference = setA.difference(setB);
console.log([...difference]); // [1, 2, 3]
// Symmetric Difference - éléments dans A ou B, mais pas dans les deux
const symmetricDiff = setA.symmetricDifference(setB);
console.log([...symmetricDiff]); // [1, 2, 3, 6, 7, 8]Méthodes de Vérification
const admins = new Set(['alice', 'bob']);
const users = new Set(['alice', 'bob', 'charlie', 'diana']);
const guests = new Set(['eve', 'frank']);
// isSubsetOf - A est contenu dans B ?
console.log(admins.isSubsetOf(users)); // true
console.log(users.isSubsetOf(admins)); // false
// isSupersetOf - A contient B ?
console.log(users.isSupersetOf(admins)); // true
// isDisjointFrom - A et B n'ont pas d'éléments en commun ?
console.log(admins.isDisjointFrom(guests)); // true
console.log(admins.isDisjointFrom(users)); // falseApplication Pratique : Système de Permissions
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('A toutes :', pm.hasAllPermissions(userPerms, required)); // false
console.log('Manquantes :', [...pm.getMissingPermissions(userPerms, required)]); // ['delete']
Promise.try : Traitement Unifié des Erreurs
Promise.try résout un problème courant : quand vous avez une fonction qui peut être synchrone ou asynchrone et que vous voulez traiter les erreurs de manière unifiée.
Le Problème
// AVANT : Code inconsistant
function processData(data) {
// Si ceci lance une erreur synchrone, le catch ne la capture pas !
return validateSync(data)
.then(validated => transform(validated))
.catch(err => console.error(err));
}
// Ancienne solution (verbeuse)
function processDataOld(data) {
return new Promise(resolve => resolve(validateSync(data)))
.then(validated => transform(validated))
.catch(err => console.error(err));
}La Solution avec Promise.try
// MAINTENANT : Propre et consistant
function processData(data) {
return Promise.try(() => validateSync(data))
.then(validated => transform(validated))
.catch(err => console.error(err));
}
// Fonctionne avec les fonctions sync et async
const result1 = Promise.try(() => {
return 42; // synchrone
});
const result2 = Promise.try(async () => {
const response = await fetch('/api/data');
return response.json(); // asynchrone
});
// Les erreurs synchrones sont capturées
const result3 = Promise.try(() => {
throw new Error('Sync error');
}).catch(err => {
console.log('Capturée :', err.message); // Capturée : Sync error
});RegExp.escape : Échappement Sécurisé de Chaînes
Quand vous devez utiliser une entrée utilisateur dans une regex, échapper les caractères spéciaux était manuel et sujet aux erreurs.
// AVANT : Fonction manuelle (courante dans les projets)
function escapeRegExpOld(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// MAINTENANT : Méthode native
const userInput = 'Hello (World)? [Test]';
const escaped = RegExp.escape(userInput);
console.log(escaped); // Hello \(World\)\? \[Test\]
// Usage sécurisé en regex dynamique
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 : Métadonnées dans les Imports
Les Import Attributes permettent de passer des informations additionnelles lors de l'import de modules, particulièrement utile pour JSON et autres types de fichiers.
// Import de JSON avec assertion de type
import config from './config.json' with { type: 'json' };
// Import dynamique avec attributs
const data = await import('./data.json', {
with: { type: 'json' }
});
// Cela aide les engines à optimiser et valider les imports
// Améliore aussi la sécurité en explicitant le type attenduCompatibilité et Adoption
Support dans les Navigateurs
| Fonctionnalité | 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+ | En développement | 18+ | 22+ |
| RegExp.escape | En développement | En développement | 18+ | 22+ |
Utilisation Aujourd'hui avec les Transpileurs
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: { node: 'current' },
shippedProposals: true,
}],
],
};Conclusion
ECMAScript 2025 n'a peut-être pas l'impact visuel d'additions comme async/await ou optional chaining, mais chaque fonctionnalité résout des problèmes pratiques. Float16Array va bénéficier aux applications graphiques et d'IA, les Set Methods simplifient du code qui était auparavant verbeux, et Promise.try standardise quelque chose que les développeurs implémentaient de différentes manières.
L'évolution incrémentale de JavaScript montre la maturité du langage. Nous n'avons pas besoin de révolutions chaque année ; des améliorations ponctuelles et bien pensées maintiennent le langage moderne sans casser la compatibilité.
Si vous voulez suivre plus de nouveautés sur JavaScript et le développement web, je recommande de jeter un œil à l'article sur Svelte 5 et Runes où nous explorons une autre innovation qui transforme la façon dont nous écrivons du code réactif.
C'est parti ! 🦅
📚 Vous Voulez Approfondir Vos Connaissances en JavaScript ?
Cet article a couvert les nouveautés d'ECMAScript 2025, mais il y a beaucoup plus à explorer dans l'écosystème JavaScript.
Les développeurs qui maîtrisent les fondamentaux et suivent l'évolution du langage se démarquent sur le marché.
Matériel d'Étude Complet
Si vous voulez maîtriser JavaScript du niveau débutant à avancé, j'ai préparé un guide complet :
Options d'investissement :
- 1x de 9,90€ par carte
- ou 9,90€ comptant
👉 Découvrir le Guide JavaScript
💡 Matériel mis à jour avec les meilleures pratiques du marché

