ECMAScript 2022 (ES13) a été abandonné le 22 juin, codifiant le dernier lot de nouvelles fonctionnalités pour JavaScript. Chaque spécification technologique est une étape importante dans une danse continue avec une utilisation dans le monde réel. Au fur et à mesure que les développeurs utilisent JavaScript, nous découvrons continuellement des opportunités et poussons le langage vers de nouveaux territoires. La spécification ECMAScript répond en formalisant de nouvelles fonctionnalités. Celles-ci, à leur tour, établissent une nouvelle base pour l’évolution continue de JavaScript.
La spécification ES13 apporte huit nouvelles fonctionnalités pour JavaScript. Commençons par ces nouvelles fonctionnalités que vous pouvez utiliser dès aujourd’hui.
Champs de classe
Les champs de classe sont une proposition globale qui englobe plusieurs améliorations pour la gestion des membres sur les classes JavaScript : champs d’instance publics et privés de classe, méthodes et accesseurs d’instance privés et fonctionnalités de classe statique.
Champs d’instance publics et privés
Auparavant, l’approche standard lors de la déclaration d’un champ membre à l’intérieur du class
mot clé était de l’introduire dans le constructeur. La dernière spécification ECMAScript nous permet de définir le champ membre en ligne dans le cadre du corps de la classe. Comme indiqué dans la liste 1, nous pouvons utiliser un hashtag pour désigner un champ privé.
Liste 1. Champs de classe publics et privés en ligne
class Song {
title = "";
#artist = "";
constructor(title, artist){
this.title = title;
this.#artist = artist;
}
}
let song1 = new Song("Only a Song", "Van Morrison");
console.log(song1.title);
// outputs “Only a Song”
console.log(song1.artist);
// outputs undefined
Dans le Listing 1, nous définissons une classe, Song
en utilisant le class
mot-clé. Cette classe compte deux membres, title
et artist
. La artist
Le membre est précédé d’un symbole dièse (#), il est donc privé. Nous permettons de définir ces champs dans le constructeur. Notez que le constructeur doit accéder this.#artist
avec le préfixe de hachage à nouveau ; sinon, il écraserait le champ avec un membre public.
Ensuite, nous définissons une instance de Song
classe, en définissant les deux champs via le constructeur. Nous sortons ensuite les champs dans la console. Le fait est que song1.artist
n’est pas visible du monde extérieur, et les sorties sont indéfinies.
A noter également que même song1.hasOwnProperty("artist")
renverra faux. De plus, nous ne pouvons pas créer de champs privés sur la classe ultérieurement à l’aide de l’affectation.
Dans l’ensemble, c’est un bel ajout, ce qui rend le code plus propre. La plupart des navigateurs prennent en charge les champs d’instance publics et privés depuis un certain temps et il est agréable de les voir officiellement incorporés.
Méthodes d’instance privée et accesseurs
Le symbole dièse fonctionne également comme préfixe sur les méthodes et les accesseurs. L’effet sur la visibilité est exactement le même qu’avec les champs d’instance privée. Ainsi, vous pouvez ajouter un setter privé et un getter public au Song.artist
champ, comme indiqué dans la liste 2.
Listing 2. Méthodes d’instance privée et accesseurs
class Song {
title = "";
#artist = "";
constructor(title, artist){
this.title = title;
this.#artist = artist;
}
get getArtist() {
return this.#artist;
}
set #setArtist(artist) {
this.#artist = artist;
}
}
membres statiques
La proposition de champs de classe introduit également des membres statiques. Celles-ci ressemblent et fonctionnent de la même manière qu’en Java : si un membre a le static
modificateur de mot-clé, il existe sur la classe au lieu des instances d’objet. Vous pouvez ajouter un membre statique au Song
classe comme indiqué dans la liste 3.
Listing 3. Ajouter un membre statique à une classe
class Song {
static label = "Exile";
}
Le champ n’est alors accessible que via le nom de la classe, Song.label
. Contrairement à Java, les instances JavaScript ne contiennent pas de référence à la variable statique partagée. Notez qu’il est possible d’avoir un champ privé statique avec des #label
; c’est-à-dire un champ statique privé.
Indices de correspondance RegExp
Regex match
a été mis à jour pour inclure plus d’informations sur les groupes correspondants. Pour des raisons de performance, ces informations ne sont incluses que si le /d
flag est ajouté à l’expression régulière. (Voir la proposition RegExp Match Indices for ECMAScript pour une analyse approfondie de la signification de /d
regex.)
Fondamentalement, en utilisant le /d
flag force le moteur regex à inclure le début et la fin de toutes les sous-chaînes correspondantes. Lorsque le drapeau est présent, le indices
propriété sur le exec
les résultats contiendront un tableau à deux dimensions, où la première dimension représente le match et la deuxième dimension représente le début et la fin du match.
Dans le cas de groupes nommés, les indices auront un membre appelé groups
, dont la première dimension contient le nom du groupe. Considérez la liste 4, qui est tirée de la proposition.
Listing 4. Indices de groupe Regex
const re1 = /a+(?z)?/d;
// block 1
const s1 = "xaaaz";
const m1 = re1.exec(s1);
m1.indices[0][0] === 1;
m1.indices[0][1] === 5;
s1.slice(...m1.indices[0]) === "aaaz";
// block 2
m1.indices[1][0] === 4;
m1.indices[1][1] === 5;
s1.slice(...m1.indices[1]) === "z";
// block 3
m1.indices.groups["Z"][0] === 4;
m1.indices.groups["Z"][1] === 5;
s1.slice(...m1.indices.groups["Z"]) === "z";
// block 4
const m2 = re1.exec("xaaay");
m2.indices[1] === undefined;
m2.indices.groups["Z"] === undefined;
Dans le Listing 4, nous créons une expression régulière qui correspond à la a
char une ou plusieurs fois, suivi d’un groupe correspondant nommé (nommé Z
) qui correspond à z
char zéro ou plusieurs fois.
Le bloc de code 1 démontre que m1.indices[0][0]
et m1.indices[0][1]
contiennent respectivement 1 et 5. C’est parce que la première correspondance pour l’expression régulière est la chaîne du premier a
à la chaîne se terminant par z
. Le bloc 2 montre la même chose pour le z
personnage.
Le bloc 3 montre comment accéder à la première dimension avec le groupe nommé via m1.indices.groups
. Il y a un groupe apparié, la finale z
caractère, et il a un début de 4 et une fin de 5.
Enfin, le bloc 4 montre que les index et les groupes sans correspondance renverront undefined.
L’essentiel est que si vous avez besoin d’accéder aux détails de l’endroit où les groupes sont mis en correspondance dans une chaîne, vous pouvez maintenant utiliser la fonction d’index de correspondance regex pour l’obtenir.
Attente de haut niveau
La spécification ECMAScript inclut désormais la possibilité de conditionner des modules asynchrones. Lorsque vous importez un module encapsulé dans await
le module inclus ne s’exécutera pas tant que tous les await
s sont remplies. Cela évite les conditions de concurrence potentielles lors du traitement d’appels de modules asynchrones interdépendants. Voir la proposition d’attente de niveau supérieur pour plus de détails.
Le Listing 5 comprend un exemple emprunté à la proposition.
Listing 5. Attente de haut niveau
// awaiting.mjs
import { process } from "./some-module.mjs";
const dynamic = import(computedModuleSpecifier);
const data = fetch(url);
export const output = process((await dynamic).default, await data);
// usage.mjs
import { output } from "./awaiting.mjs";
export function outputPlusValue(value) { return output + value }
console.log(outputPlusValue(100));
setTimeout(() => console.log(outputPlusValue(100), 1000);
Avis dans awaiting.mjs
la await
mot-clé devant son utilisation de modules dépendants dynamic
et data
. Cela signifie que lorsque usage.mjs
importations awaiting.mjs
, usage.mjs
ne sera pas exécuté avant awaiting.mjs
les dépendances ont fini de se charger.
Contrôles de marque ergonomiques pour les champs privés
En tant que développeurs, nous voulons un code confortable, c’est-à-dire des champs privés ergonomiques. Cette nouvelle fonctionnalité nous permet de vérifier l’existence d’un champ privé sur une classe sans recourir à la gestion des exceptions.
Le Listing 6 montre cette nouvelle façon ergonomique de rechercher un champ privé à partir d’une classe, en utilisant la in
mot-clé.
Listing 6. Vérifier l’existence d’un champ privé
class Song {
#artist;
checkField(){
return #artist in this;
}
}
let foo = new Song();
foo.checkField(); // true
Le listing 6 est artificiel, mais l’idée est claire. Lorsque vous avez besoin de vérifier une classe pour un champ privé, vous pouvez utiliser le format : #fieldName in object
.
Indexation négative avec .at()
Fini le temps des arr[arr.length -2]
. La méthode .at sur les indexables intégrés prend désormais en charge les indices négatifs, comme indiqué dans le Listing 7.
Listing 7. Index négatif avec .at()
let foo = [1,2,3,4,5];
foo.at(3); // == 3
hasOwn
possède
Object.hasOwn est une version améliorée de Object.hasOwnProperty
. Cela fonctionne pour certains cas extrêmes, comme lorsqu’un objet est créé avec Object.create(null)
. Notez que hasOwn
est une méthode statique — elle n’existe pas sur les instances.
Listing 8. hasOwn() en action
let foo = Object.create(null);
foo.hasOwnProperty = function(){};
Object.hasOwnProperty(foo, 'hasOwnProperty'); // Error: Cannot convert object to primitive value
Object.hasOwn(foo, 'hasOwnProperty'); // true
Le Listing 8 montre que vous pouvez utiliser Object.hasOwn
sur le foo
instance créée avec Object.create(null)
.
Bloc statique de classe
Voici une chance pour les développeurs Java de dire, Oh, nous avons ça depuis les années 90. ES 2022 introduit des blocs d’initialisation statiques dans JavaScript. En gros, vous pouvez utiliser le static
mot-clé sur un bloc de code qui est exécuté lorsque la classe est chargée, et il aura accès aux membres statiques.
Le Listing 9 présente un exemple simple d’utilisation d’un bloc statique pour initialiser une valeur statique.
Listing 9. Bloc statique
class Foo {
static bar;
static {
this.bar = “test”;
}
}
Cause de l’erreur
Dernier point mais non le moindre, le Error
la classe intègre désormais le support de cause. Cela permet des traces de pile de type Java dans les chaînes d’erreurs. Le constructeur d’erreur permet désormais un objet d’options qui inclut un cause
champ, comme indiqué dans le Listing 10.
Listing 10. Cause de l’erreur
throw new Error('Error message', { cause: errorCause });
Copyright © 2022 IDG Communications, Inc.