8 nouvelles fonctionnalités JavaScript à utiliser dès aujourd’hui

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, Songen 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 awaitle module inclus ne s’exécutera pas tant que tous les awaits 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.

Leave a Comment