Aller au contenu principal

13 articles tagués avec « io19 »

Voir tous les tags

`Intl.NumberFormat`

· 5 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias)) et Shane F. Carr

Vous connaissez peut-être déjà l’API Intl.NumberFormat, car elle est prise en charge dans les environnements modernes depuis un certain temps.

Dans sa forme la plus basique, Intl.NumberFormat vous permet de créer une instance de formateur réutilisable qui prend en charge le formatage des nombres adapté à la langue locale. Tout comme les autres API Intl.*Format, une instance de formateur prend en charge les méthodes format et formatToParts :

`globalThis`

· 2 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Si vous avez déjà écrit du JavaScript pour une utilisation dans un navigateur web, vous avez peut-être utilisé window pour accéder au this global. Dans Node.js, vous avez peut-être utilisé global. Si vous avez écrit du code qui doit fonctionner dans les deux environnements, vous avez peut-être détecté lequel de ces éléments est disponible, puis utilisé celui-ci — mais la liste des identifiants à vérifier s'allonge avec le nombre d'environnements et de cas d'utilisation que vous souhaitez prendre en charge. Cela devient vite ingérable :

Références faibles et finalisateurs

· 11 minutes de lecture
Sathya Gunasekaran ([@_gsathya](https://twitter.com/_gsathya)), Mathias Bynens ([@mathias](https://twitter.com/mathias)), Shu-yu Guo ([@_shu](https://twitter.com/_shu)), et Leszek Swirski ([@leszekswirski](https://twitter.com/leszekswirski))

Généralement, les références aux objets sont fortement conservées en JavaScript, ce qui signifie que tant que vous avez une référence à l'objet, il ne sera pas collecté par le garbage collector.

const ref = { x: 42, y: 51 };
// Tant que vous avez accès à `ref` (ou toute autre référence
// au même objet), l'objet ne sera pas collecté par le garbage collector.

Actuellement, les WeakMap et WeakSet sont les seuls moyens de référencer un objet de manière quasi-faible en JavaScript : ajouter un objet en tant que clé à un WeakMap ou WeakSet ne l'empêche pas d'être collecté par le garbage collector.

const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// Nous n'avons plus de référence à `ref` dans ce bloc de portée, donc
// il peut être collecté par le garbage collector, même s'il est une clé
// dans `wm` auquel nous avons encore accès.

Trie stable `Array.prototype.sort`

· 4 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Disons que vous avez un tableau de chiens, où chaque chien a un nom et une note. (Si cet exemple vous semble bizarre, sachez qu'il existe un compte Twitter qui se spécialise exactement là-dedans… Ne demandez pas !)

// Notez comment le tableau est pré-trié par ordre alphabétique par `name`.
const doggos = [
{ name: 'Abby', rating: 12 },
{ name: 'Bandit', rating: 13 },
{ name: 'Choco', rating: 14 },
{ name: 'Daisy', rating: 12 },
{ name: 'Elmo', rating: 12 },
{ name: 'Falco', rating: 13 },
{ name: 'Ghost', rating: 14 },
];
// Triez les chiens par `rating` en ordre décroissant.
// (Cela met à jour `doggos` en place.)
doggos.sort((a, b) => b.rating - a.rating);

`Object.fromEntries`

· 4 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias)), spécialiste en JavaScript

Object.fromEntries est un ajout utile à la bibliothèque JavaScript intégrée. Avant d'expliquer ce qu'il fait, il est utile de comprendre l'API existante Object.entries.

Object.entries

L'API Object.entries existe depuis un certain temps.

Pour chaque paire clé-valeur dans un objet, Object.entries vous donne un tableau où le premier élément est la clé et le second élément est la valeur.

Object.entries est particulièrement utile en combinaison avec for-of, car il vous permet d'itérer très élégamment sur toutes les paires clé-valeur d'un objet :

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

for (const [key, value] of entries) {
console.log(`La valeur de ${key} est ${value}.`);
}
// Affiche :
// La valeur de x est 42.
// La valeur de y est 50.

Malheureusement, il n'y a pas de moyen facile de revenir du résultat des entries à un objet équivalent… jusqu'à maintenant !

Object.fromEntries

La nouvelle API Object.fromEntries effectue l'inverse de Object.entries. Cela facilite la reconstruction d'un objet à partir de ses entries :

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

const result = Object.fromEntries(entries);
// → { x: 42, y: 50 }

Un cas d'utilisation courant est la transformation d'objets. Vous pouvez maintenant faire cela en itérant sur ses entries, puis en utilisant des méthodes de tableau que vous connaissez probablement déjà :

const object = { x: 42, y: 50, abc: 9001 };
const result = Object.fromEntries(
Object.entries(object)
.filter(([ key, value ]) => key.length === 1)
.map(([ key, value ]) => [ key, value * 2 ])
);
// → { x: 84, y: 100 }

Dans cet exemple, nous appliquons un filter sur l'objet pour ne récupérer que les clés de longueur 1, c'est-à-dire seulement les clés x et y, mais pas la clé abc. Nous effectuons ensuite un map sur les entries restantes et retournons une paire clé-valeur mise à jour pour chacune. Dans cet exemple, nous doublons chaque valeur en la multipliant par 2. Le résultat final est un nouvel objet, avec uniquement les propriétés x et y, et les nouvelles valeurs.

Promise combinators

· 5 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Depuis l'introduction des promesses dans ES2015, JavaScript a pris en charge exactement deux combinateurs de promesses : les méthodes statiques Promise.all et Promise.race.

Deux nouvelles propositions sont actuellement en cours de standardisation : Promise.allSettled et Promise.any. Avec ces ajouts, il y aura un total de quatre combinateurs de promesses en JavaScript, chacun permettant différents cas d'utilisation.

`Array.prototype.flat` et `Array.prototype.flatMap`

· 2 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Array.prototype.flat

Le tableau dans cet exemple est profond de plusieurs niveaux : il contient un tableau qui lui-même contient un autre tableau.

const array = [1, [2, [3]]];
// ^^^^^^^^^^^^^ tableau extérieur
// ^^^^^^^^ tableau intérieur
// ^^^ tableau le plus intérieur

Array#flat retourne une version aplatie d'un tableau donné.

array.flat();
// → [1, 2, [3]]

// …est équivalent à :
array.flat(1);
// → [1, 2, [3]]

La profondeur par défaut est 1, mais vous pouvez passer n'importe quel nombre pour aplatir récursivement jusqu'à cette profondeur. Pour continuer d'aplatir récursivement jusqu'à ce que le résultat ne contienne plus de tableaux imbriqués, on passe Infinity.

// Aplatir récursivement jusqu'à ce que le tableau ne contienne plus de tableaux imbriqués :
array.flat(Infinity);
// → [1, 2, 3]

Pourquoi cette méthode s'appelle-t-elle Array.prototype.flat et non Array.prototype.flatten ? Lisez notre article sur le #SmooshGate pour le découvrir !

Array.prototype.flatMap

Voici un autre exemple. Nous avons une fonction duplicate qui prend une valeur et retourne un tableau contenant cette valeur deux fois. Si nous appliquons duplicate à chaque valeur d'un tableau, nous obtenons un tableau imbriqué.

const duplicate = (x) => [x, x];

[2, 3, 4].map(duplicate);
// → [[2, 2], [3, 3], [4, 4]]

Vous pouvez ensuite appeler flat sur le résultat pour aplatir le tableau :

[2, 3, 4].map(duplicate).flat(); // 🐌
// → [2, 2, 3, 3, 4, 4]

Étant donné que ce schéma est très courant en programmation fonctionnelle, il existe maintenant une méthode dédiée flatMap pour cela.

[2, 3, 4].flatMap(duplicate); // 🚀
// → [2, 2, 3, 3, 4, 4]

flatMap est un peu plus efficace que d'effectuer un map suivi d'un flat séparément.

Vous êtes intéressé par les cas d'utilisation de flatMap ? Découvrez l'explication d'Axel Rauschmayer.

Prise en charge de Array#{flat,flatMap}

Séparateurs numériques

· 2 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Les grands littéraux numériques sont difficiles à analyser rapidement pour l'œil humain, surtout lorsqu'il y a beaucoup de chiffres répétitifs :

1000000000000
1019436871.42

Pour améliorer la lisibilité, une nouvelle fonctionnalité de langage JavaScript permet d'utiliser des underscores comme séparateurs dans les littéraux numériques. Ainsi, cela peut désormais être réécrit en regroupant les chiffres par mille, par exemple :

`String.prototype.matchAll`

· 3 minutes de lecture
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Il est courant d'appliquer à plusieurs reprises la même expression régulière sur une chaîne pour obtenir toutes les correspondances. Dans une certaine mesure, cela est déjà possible aujourd'hui en utilisant la méthode String#match.

Dans cet exemple, nous trouvons tous les mots constitués uniquement de chiffres hexadécimaux, puis nous enregistrons chaque correspondance :

const string = 'Nombres hex magiques : DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.match(regex)) {
console.log(match);
}

// Résultat :
//
// 'DEADBEEF'
// 'CAFE'

Cependant, cela ne vous donne que les sous-chaînes qui correspondent. Habituellement, vous ne voulez pas seulement les sous-chaînes, mais aussi des informations supplémentaires telles que l'index de chaque sous-chaîne ou les groupes capturés dans chaque correspondance.

Il est déjà possible de faire cela en écrivant votre propre boucle et en suivant vous-même les objets correspondants, mais cela peut être un peu irritant et pas très pratique :

const string = 'Nombres hex magiques : DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
let match;
while (match = regex.exec(string)) {
console.log(match);
}

// Résultat :
//
// [ 'DEADBEEF', index: 19, input: 'Nombres hex magiques : DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Nombres hex magiques : DEADBEEF CAFE' ]

La nouvelle API String#matchAll rend cela plus facile que jamais : vous pouvez désormais écrire une simple boucle for-of pour obtenir tous les objets correspondants.

const string = 'Nombres hex magiques : DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.matchAll(regex)) {
console.log(match);
}

// Résultat :
//
// [ 'DEADBEEF', index: 19, input: 'Nombres hex magiques : DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Nombres hex magiques : DEADBEEF CAFE' ]

String#matchAll est particulièrement utile pour les expressions régulières avec des groupes de capture. Elle vous donne des informations complètes pour chaque correspondance individuelle, y compris les groupes capturés.

const string = 'Dépôts GitHub préférés : tc39/ecma262 v8/v8.dev';
const regex = /\b(?<owner>[a-z0-9]+)\/(?<repo>[a-z0-9\.]+)\b/g;
for (const match of string.matchAll(regex)) {
console.log(`${match[0]} at ${match.index} with '${match.input}'`);
console.log(`→ propriétaire : ${match.groups.owner}`);
console.log(`→ dépôt : ${match.groups.repo}`);
}

`Intl.ListFormat`

· 4 minutes de lecture
Mathias Bynens ([[@mathias](https://twitter.com/mathias)) et Frank Yung-Fong Tang

Les applications web modernes utilisent souvent des listes composées de données dynamiques. Par exemple, une application de visualisation de photos peut afficher quelque chose comme :

Cette photo inclut Ada, Edith, et Grace.

Un jeu basé sur du texte peut avoir un type de liste différent :

Choisissez votre superpuissance : invisibilité, psychokinésie, ou empathie.

Étant donné que chaque langue a des conventions de formatage de liste différentes, ainsi que des mots différents, la mise en œuvre d'un formateur de liste localisée est complexe. Non seulement cela nécessite une liste de tous les mots (comme « et » ou « ou » dans les exemples ci-dessus) pour chaque langue que vous souhaitez prendre en charge — mais il faut également coder les conventions de formatage exactes pour toutes ces langues ! Le CLDR Unicode fournit ces données, mais pour les utiliser en JavaScript, elles doivent être intégrées et embarquées avec les autres codes de la bibliothèque. Cela augmente malheureusement la taille du bundle pour de telles bibliothèques, ce qui a des impacts négatifs sur les temps de chargement, les coûts de parse/compilation, et la consommation de mémoire.