Aller au contenu principal

9 articles tagués avec « ES2019 »

Voir tous les tags

Incorporer JSON, autrement dit JSON ⊂ ECMAScript

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

Avec la proposition JSON ⊂ ECMAScript, JSON devient un sous-ensemble syntaxique d'ECMAScript. Si vous êtes surpris que cela n'était pas déjà le cas, vous n'êtes pas le seul !

Le comportement ancien d'ES2018

En ES2018, les littéraux de chaîne de caractères d'ECMAScript ne pouvaient pas contenir les caractères séparateurs de ligne U+2028 LINE SEPARATOR et U+2029 PARAGRAPH SEPARATOR non échappés, car ils sont considérés comme des terminaux de ligne même dans ce contexte :

// Une chaîne contenant un caractère U+2028 brut.
const LS = '
';
// → ES2018 : SyntaxError

// Une chaîne contenant un caractère U+2029 brut, produit par `eval` :
const PS = eval('"\u2029"');
// → ES2018 : SyntaxError

Cela posait problème car les chaînes JSON peuvent contenir ces caractères. En conséquence, les développeurs devaient implémenter une logique de post-traitement spécialisée lors de l'intégration de JSON valide dans des programmes ECMAScript pour gérer ces caractères. Sans cette logique, le code pouvait comporter des bugs subtils, voire des problèmes de sécurité !

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);

`Symbol.prototype.description`

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

Les Symbol en JavaScript peuvent recevoir une description lors de leur création :

const symbol = Symbol('foo');
// ^^^^^

Auparavant, la seule façon d'accéder à cette description par programme était de manière indirecte via Symbol.prototype.toString() :

const symbol = Symbol('foo');
// ^^^^^
symbol.toString();
// → 'Symbol(foo)'
// ^^^
symbol.toString().slice(7, -1); // 🤔
// → 'foo'

Cependant, ce code semble légèrement magique, pas très explicite, et viole le principe « exprimer l'intention, non l'implémentation ». Cette technique ne permet pas non plus de faire la distinction entre un symbole sans description (c'est-à-dire Symbol()) et un symbole dont la description est une chaîne vide (c'est-à-dire Symbol('')).

`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.

`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}

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) :

Variable `catch` facultative

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

La clause catch des instructions try nécessitait un paramètre :

try {
faireQuelqueChoseQuiPeutJeterErreur();
} catch (exception) {
// ^^^^^^^^^
// Nous devons nommer le paramètre, même si nous ne l'utilisons pas !
gérerException();
}

En ES2019, catch peut maintenant être utilisé sans paramètre. Cela est utile si vous n’avez pas besoin de l’objet exception dans le code qui gère l’exception.

try {
faireQuelqueChoseQuiPeutJeterErreur();
} catch { // → Pas de paramètre !
gérerException();
}

Prise en charge de la variable catch facultative

`String.prototype.trimStart` et `String.prototype.trimEnd`

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

ES2019 introduit String.prototype.trimStart() et String.prototype.trimEnd() :

const string = '  bonjour le monde  ';
string.trimStart();
// → 'bonjour le monde '
string.trimEnd();
// → ' bonjour le monde'
string.trim(); // ES5
// → 'bonjour le monde'

Cette fonctionnalité était auparavant disponible via les méthodes non standard trimLeft() et trimRight(), qui restent comme alias des nouvelles méthodes pour la compatibilité ascendante.

const string = '  bonjour le monde  ';
string.trimStart();
// → 'bonjour le monde '
string.trimLeft();
// → 'bonjour le monde '
string.trimEnd();
// → ' bonjour le monde'
string.trimRight();
// → ' bonjour le monde'
string.trim(); // ES5
// → 'bonjour le monde'