Aller au contenu principal

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.

Exports de l'espace de noms des modules

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

Dans les modules JavaScript, il était déjà possible d'utiliser la syntaxe suivante :

import * as utils from './utils.mjs';

Cependant, aucune syntaxe d'exportation symétrique n'existait… jusqu'à maintenant :

export * as utils from './utils.mjs';

Cela équivaut à ce qui suit :

import * as utils from './utils.mjs';
export { utils };

Champs de classe publics et privés

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

Plusieurs propositions étendent la syntaxe existante des classes JavaScript avec de nouvelles fonctionnalités. Cet article explique la nouvelle syntaxe des champs de classe publics dans V8 v7.2 et Chrome 72, ainsi que la syntaxe des champs de classe privés à venir.

Voici un exemple de code qui crée une instance d'une classe nommée IncreasingCounter :

const counter = new IncreasingCounter();
counter.value;
// affiche 'Récupération de la valeur actuelle !'
// → 0
counter.increment();
counter.value;
// affiche 'Récupération de la valeur actuelle !'
// → 1

Notez que l'accès à la propriété value exécute du code (c'est-à-dire qu'il affiche un message) avant de retourner le résultat. Maintenant demandez-vous, comment implémenteriez-vous cette classe en JavaScript ? 🤔

Syntaxe des classes ES2015

Voici comment IncreasingCounter pourrait être implémenté en utilisant la syntaxe des classes ES2015 :

class IncreasingCounter {
constructor() {
this._count = 0;
}
get value() {
console.log('Récupération de la valeur actuelle !');
return this._count;
}
increment() {
this._count++;
}
}

La classe installe le getter value et une méthode increment sur le prototype. Plus intéressant encore, la classe dispose d'un constructeur qui crée une propriété d'instance _count et définit sa valeur par défaut à 0. Nous avons actuellement tendance à utiliser le préfixe de soulignement pour indiquer que _count ne doit pas être utilisé directement par les consommateurs de la classe, mais ce n'est qu'une convention ; il ne s'agit pas vraiment d'une propriété « privée » avec des sémantiques spéciales appliquées par le langage.

`Intl.RelativeTimeFormat`

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

Les applications web modernes utilisent souvent des phrases comme « hier », « il y a 42 secondes », ou « dans 3 mois » au lieu de dates complètes et de marques temporelles. Ces valeurs formatées en temps relatif sont devenues si courantes que plusieurs bibliothèques populaires implémentent des fonctions utilitaires pour les formater de manière localisée. (Des exemples incluent Moment.js, Globalize, et date-fns.)

Un `JSON.stringify` bien formé

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

JSON.stringify était précédemment spécifié pour retourner des chaînes Unicode mal formées si l'entrée contenait des solitaires :

JSON.stringify('\uD800');
// → '"�"'

La proposition “Un JSON.stringify bien formé” modifie JSON.stringify pour qu'il génère des séquences d'échappement pour les solitaires, rendant sa sortie un Unicode valide (et représentable en UTF-8) :

Modules JavaScript

· 23 minutes de lecture
Addy Osmani ([@addyosmani](https://twitter.com/addyosmani)) et Mathias Bynens ([@mathias](https://twitter.com/mathias))

Les modules JavaScript sont désormais pris en charge dans tous les principaux navigateurs !

Cet article explique comment utiliser les modules JS, comment les déployer de manière responsable et comment l'équipe Chrome travaille pour les améliorer encore à l'avenir.

Que sont les modules JS ?

Les modules JS (également connus sous le nom de “modules ES” ou “modules ECMAScript”) sont une nouvelle fonctionnalité majeure, ou plutôt un ensemble de nouvelles fonctionnalités. Vous avez peut-être utilisé un système de modules JavaScript utilisateur dans le passé. Peut-être avez-vous utilisé CommonJS comme dans Node.js, ou peut-être AMD, ou peut-être autre chose. Tous ces systèmes de modules ont une chose en commun : ils vous permettent d'importer et d'exporter des éléments.