Le matériel, la première partie de la traduction que nous publions aujourd'hui, est consacré aux nouvelles fonctionnalités JavaScript standard qui ont été discutées lors de la conférence
Google I / O 2019 . En particulier, nous parlerons ici des expressions régulières, des champs de classe, de l'utilisation des chaînes.

Contrôles d'expression régulière
Les expressions régulières (Regular Expression, pour faire court - RegEx ou RegExp) est une technologie de traitement de chaîne puissante qui est implémentée dans de nombreux langages de programmation. Les expressions régulières sont très utiles dans les cas où vous devez, par exemple, rechercher des fragments de chaînes par des motifs complexes. Jusqu'à récemment, l'implémentation JavaScript des expressions régulières avait tout sauf des backbacks.
Afin de comprendre ce qu'est un contrôle rétrospectif, parlons d'abord des têtes de recherche déjà prises en charge par JavaScript.
→
La deuxième partie▍ Contrôle préalable
La syntaxe des contrôles de tête dans les expressions régulières vous permet de rechercher des fragments de chaînes lorsque l'on sait que d'autres fragments se trouvent à leur droite. Par exemple, lorsque vous travaillez avec la chaîne
MangoJuice, VanillaShake, GrapeJuice
vous pouvez utiliser la syntaxe d'un contrôle de
MangoJuice, VanillaShake, GrapeJuice
positif pour rechercher les mots immédiatement suivis du mot
Juice
. Dans notre cas, ce sont les mots
Mango
et
Grape
.
Il existe deux types de contrôles principaux. Il s'agit de têtes de recherche positives et de têtes de recherche négatives.
Vérification positive du plomb
Un contrôle de début positif est utilisé pour rechercher des lignes à droite desquelles se trouvent d'autres lignes précédemment connues. Voici à quoi ressemble la syntaxe d'expression régulière utilisée pour cette vérification:
/[a-zA-Z]+(?=Juice)/
Ce modèle vous permet de sélectionner des mots composés de lettres minuscules ou majuscules, suivis du mot
Juice
. Ne confondez pas les structures décrivant les contrôles principaux et rétrospectifs avec les groupes de capture. Bien que les conditions de ces vérifications soient écrites entre parenthèses, le système ne les capture pas. Regardons un exemple de vérification positive du plomb.
const testString = "MangoJuice, VanillaShake, GrapeJuice"; const testRegExp = /[a-zA-Z]+(?=Juice)/g; const matches = testString.match( testRegExp ); console.log( matches );
Vérification de plomb négatif
Si nous considérons, en utilisant la ligne ci-dessus, le mécanisme d'action des contrôles de tête négatifs, il s'avère qu'ils vous permettent de trouver des mots à la droite desquels il n'y a pas de mot
Juice
. La syntaxe des contrôles de tête négatifs est similaire à la syntaxe des contrôles positifs. Cependant, il y a une caractéristique, c'est que le symbole
=
(égal) change en symbole
!
(point d'exclamation). Voici à quoi ça ressemble:
/[a-zA-Z]+(?!Juice)/
Cette expression régulière vous permet de sélectionner tous les mots à la droite desquels il n'y a pas de mot
Juice
. Mais lors de l'application d'un tel modèle, tous les mots de la ligne seront sélectionnés (
MangoJuice, VanillaShake, GrapeJuice
). Le fait est que, selon le système, pas un seul mot ne se termine ici par
Juice
. Par conséquent, afin d'obtenir le résultat souhaité, vous devez clarifier l'expression régulière et la réécrire comme ceci:
/(Mango|Vanilla|Grape)(?!Juice)/
L'utilisation de ce modèle vous permet de sélectionner les mots
Mango
,
Vanilla
ou
Grape
, après quoi il n'y a pas de mot
Juice
. Voici un exemple:
const testString = "MangoJuice, VanillaShake, GrapeJuice"; const testRegExp = /(Mango|Vanilla|Grape)(?!Juice)/g; const matches = testString.match( testRegExp ); console.log( matches );
▍ Contrôle rétrospectif
Par analogie avec la syntaxe des contrôles de tête, la syntaxe des contrôles rétrospectifs vous permet de sélectionner des séquences de caractères uniquement si à gauche de ces séquences se trouve un certain modèle spécifié. Par exemple, lors du traitement de la chaîne
FrozenBananas, DriedApples, FrozenFish
nous pouvons utiliser une vérification rétrospective positive pour trouver les mots à gauche desquels se trouve le mot
Frozen
. Dans notre cas, les mots
Bananas
et
Fish
correspondent à cette condition.
Il existe, comme c'est le cas pour les contrôles de tête, les contrôles rétrospectifs positifs (lookbehind positif) et les contrôles rétrospectifs négatifs (lookbehind négatif ou négatif).
Revue rétrospective positive
Des contrôles rétrospectifs positifs sont utilisés pour rechercher des modèles à gauche desquels se trouvent d'autres modèles. Voici un exemple de la syntaxe utilisée pour décrire ces vérifications:
/(?<=Frozen)[a-zA-Z]+/
Le symbole
<
utilisé ici, ce qui n'était pas dans la description des principaux contrôles. De plus, la condition dans l'expression régulière n'est pas située à droite du modèle qui nous intéresse, mais à gauche. En utilisant le modèle ci-dessus, vous pouvez sélectionner tous les mots commençant par
Frozen
. Prenons un exemple:
const testString = "FrozenBananas, DriedApples, FrozenFish"; const testRegExp = /(?<=Frozen)[a-zA-Z]+/g; const matches = testString.match( testRegExp ); console.log( matches );
Contrôle rétrospectif négatif
Le mécanisme des contrôles rétrospectifs négatifs vous permet de rechercher des motifs dans les lignes à gauche desquelles il n'y a pas de motif spécifié. Par exemple, si vous devez sélectionner des mots qui ne commencent pas par
Frozen
dans la ligne
FrozenBananas, DriedApples, FrozenFish
, vous pouvez essayer d'utiliser cette expression régulière:
/(?<!Frozen)[a-zA-Z]+/
Mais, puisque l'utilisation de cette construction entraînera la sélection de tous les mots de la chaîne, car aucun ne commence par
Frozen
, l'expression régulière doit être clarifiée:
/(?<!Frozen)(Bananas|Apples|Fish)/
Voici un exemple:
const testString = "FrozenBananas, DriedApples, FrozenFish"; const testRegExp = /(?<!Frozen)(Bananas|Apples|Fish)/g; const matches = testString.match( testRegExp ); console.log( matches );
→ Support
Cette section et d'autres sections similaires fourniront des informations sur le stade d'harmonisation des fonctionnalités décrites de JS au sein du comité technique 39 (comité technique 39, TC39), qui est responsable au sein d'ECMA International de la prise en charge des spécifications ECMAScript. Ces sections fourniront également des données sur les versions de Chrome et Node.js (et parfois sur la version de Firefox), à partir desquelles vous pourrez utiliser les fonctionnalités correspondantes.
Champs de classe
Un champ de classe est une nouvelle construction de syntaxe utilisée pour définir les propriétés des instances de classe (objets) en dehors du constructeur de classe. Il existe deux types de champs de classe: les champs de classe publics et les champs de classe privés.
Fields Champs de classe publique
Jusqu'à récemment, les propriétés des objets devaient être définies à l'intérieur du constructeur de classe. Ces propriétés étaient publiques (publiques). Cela signifie qu'ils sont accessibles en travaillant avec une instance de la classe (objet). Voici un exemple de déclaration d'une propriété publique:
class Dog { constructor() { this.name = 'Tommy'; } }
Lorsqu'il était nécessaire de créer une classe qui étendrait une certaine classe parent, il fallait appeler
super()
dans le constructeur de la classe enfant. Cela devait être fait avant que ses propres propriétés puissent être ajoutées à la classe enfant. Voici à quoi ça ressemble:
class Animal {} class Dog extends Animal { constructor() { super();
Grâce à l'apparition de la syntaxe des champs publics d'une classe, il est possible de décrire des champs de classe en dehors du constructeur. Le système fera un appel implicite à
super()
.
class Animal {} class Dog extends Animal { sound = 'Woof! Woof!';
Lors de l'appel implicite de
super()
il passe tous les arguments fournis par l'utilisateur lors de la création de l'instance de classe (c'est un comportement JavaScript standard, il n'y a rien de spécial dans les champs de classe privés). Si le constructeur de la classe parente a besoin d'arguments préparés d'une manière spéciale, vous devez appeler vous-même
super()
. Jetez un œil aux résultats de l'appel constructeur implicite de la classe parent lors de la création d'une instance de la classe enfant.
class Animal { constructor( ...args ) { console.log( 'Animal args:', args ); } } class Dog extends Animal { sound = 'Woof! Woof!';
▍ Champs de cours privés
Comme vous le savez, en JavaScript, il n'y a pas de modificateurs d'accès aux champs de classe comme
public
,
private
ou
protected
. Toutes les propriétés des objets sont publiques par défaut. Cela signifie que leur accès est illimité. La chose la plus proche de rendre une propriété d'un objet similaire à une propriété privée est d'utiliser le type de données
Symbol
. Cela vous permet de masquer les propriétés des objets du monde extérieur. Vous avez peut-être utilisé des noms de propriété précédés d'un
_
(trait de soulignement) pour indiquer que les propriétés correspondantes doivent être considérées comme destinées uniquement à être utilisées dans l'objet. Cependant, ce n'est qu'une sorte de notification pour ceux qui utiliseront l'installation. Cela ne résout pas le problème de la restriction réelle de l'accès aux propriétés.
Grâce au mécanisme des champs privés des classes, il est possible de rendre les propriétés de classe accessibles uniquement à l'intérieur de cette classe. Cela conduit au fait qu'ils ne sont pas accessibles de l'extérieur et fonctionnent avec une instance de la classe (objet). Prenez l'exemple précédent et essayez d'accéder à la propriété de la classe de l'extérieur, lorsque le préfixe
_
été utilisé.
class Dog { _sound = 'Woof! Woof!';
Comme vous pouvez le voir, l'utilisation du préfixe
_
ne résout pas notre problème. Les champs privés des classes peuvent être déclarés de la même manière que les champs publics, mais au lieu d'un préfixe sous la forme d'un trait de soulignement, vous devez ajouter un préfixe sous la forme d'un signe dièse (
#
) à leurs noms. Une tentative d'accès non autorisé à la propriété privée de l'objet déclarée de cette manière entraînera l'erreur suivante:
SyntaxError: Undefined private field
Voici un exemple:
class Dog { #sound = 'Woof! Woof!';
Notez que les propriétés privées ne sont accessibles qu'à partir de la classe dans laquelle elles sont déclarées. Par conséquent, les classes descendantes ne peuvent pas utiliser directement les propriétés similaires de la classe parente.
Les champs privés (et publics) peuvent être déclarés sans y écrire certaines valeurs:
class Dog { #name; constructor( name ) { this.#name = name; } showName() { console.log( this.#name ); } }
→ Support
Méthode de chaîne .matchAll ()
Le prototype de type de données
String
possède une méthode
.match()
qui renvoie un tableau de fragments de chaîne correspondant à la condition spécifiée par l'expression régulière. Voici un exemple utilisant cette méthode:
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /([A-Z0-9]+)/g; console.log( colors.match( matchColorRegExp ) );
Lorsque vous utilisez cette méthode, cependant, aucune information supplémentaire n'est donnée (comme les index) sur les fragments trouvés de la chaîne. Si vous supprimez l'indicateur
g
de l'expression régulière passée à la méthode
.match()
, il renverra un tableau qui contiendra des informations supplémentaires sur les résultats de la recherche. Cependant, avec cette approche, seul le premier fragment de la chaîne correspondant à l'expression régulière sera trouvé.
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/; console.log( colors.match( matchColorRegExp ) );
Pour obtenir quelque chose de similaire, mais pour plusieurs fragments d'une chaîne, vous devrez utiliser la méthode d'expression régulière
.exec()
. Les constructions nécessaires pour cela sont plus compliquées que celle dans laquelle une méthode à chaîne unique serait utilisée pour obtenir des résultats similaires. En particulier, nous avons besoin ici d'une
while
qui s'exécutera jusqu'à
.exec()
que
.exec()
renvoie
null
. En utilisant cette approche, gardez à l'esprit que
.exec()
ne renvoie pas d'itérateur.
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/g;
Afin de résoudre ces problèmes, nous pouvons maintenant utiliser la méthode de chaîne
.matchAll()
, qui retourne un itérateur. Chaque appel à la méthode
.next()
de cet itérateur
.next()
élément suivant des résultats de la recherche. Par conséquent, l'exemple ci-dessus peut être réécrit comme suit:
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/g; console.log( ...colors.matchAll( matchColorRegExp ) );
→ Support
Groupes nommés dans les expressions régulières
Le concept de groupes dans l'implémentation JavaScript des mécanismes d'expression régulière est légèrement différent de l'implémentation d'un concept similaire dans d'autres langages. À savoir, lorsque, à l'aide de JavaScript, le modèle RegEx est placé entre parenthèses (sauf lorsque des parenthèses sont utilisées pour des vérifications rétrospectives ou avancées), le modèle devient un groupe.
Les fragments de la chaîne capturés par le groupe seront reflétés dans les résultats de l'application de l'expression régulière.
Dans l'exemple précédent, vous pouvez voir que le premier élément du tableau avec les résultats de la recherche est celui qui correspond à l'expression régulière entière, et le second est celui qui correspond au groupe. Voici cet élément de tableau:
["#EEE", "EEE", index: 0, input: "<colors>"]
S'il y a plusieurs groupes dans l'expression régulière, alors ils entreront dans les résultats du traitement de la chaîne dans l'ordre de leur description dans l'expression régulière. Prenons un exemple:
const str = "My name is John Doe."; const matchRegExp = /My name is ([az]+) ([az]+)/i; const result = str.match( matchRegExp );console.log( result );
Ici, vous pouvez voir que la première ligne de la sortie est la ligne entière correspondant à l'expression régulière. Les deuxième et troisième éléments représentent ce qui a été capturé par les groupes.
L'utilisation de groupes nommés vous permet d'enregistrer les groupes à capturer dans l'objet
groups
, dont les noms de propriété correspondent aux noms attribués aux groupes.
const str = "My name is John Doe."; const matchRegExp = /My name is (?<firstName>[az]+) (?<lastName>[az]+)/i; const result = str.match( matchRegExp ); console.log( result ); console.log( result.groups );
Il convient de noter que les groupes nommés fonctionnent
.matchAll()
avec la méthode
.matchAll()
.
→ Support
À suivre ...
Chers lecteurs! Avez-vous utilisé l'une des innovations JavaScript décrites ici?
