Guide JavaScript Partie 9: Présentation des normes ES7, ES8 et ES9

Aujourd'hui, dans la neuvième partie de la traduction du manuel JavaScript, un aperçu sera donné des fonctionnalités apparues dans le langage grâce aux normes ES7, ES8 et ES9.

Partie 1: premier programme, fonctionnalités linguistiques, normes
Partie 2: style de code et structure du programme
Partie 3: variables, types de données, expressions, objets
Partie 4: caractéristiques
Partie 5: tableaux et boucles
Partie 6: exceptions, points-virgules, littéraux génériques
Partie 7: mode strict, ce mot-clé, événements, modules, calculs mathématiques
Partie 8: Présentation des fonctionnalités d'ES6
Partie 9: Présentation des normes ES7, ES8 et ES9



Norme ES7


La norme ES7, qui, selon la terminologie officielle, s'appelle ES2016, a été publiée à l'été 2016. Lui, par rapport à ES6, apporté à la langue n'est pas très nouveau. En particulier, nous parlons de ce qui suit:

  • Array.prototype.includes() méthode.
  • Opérateur d'exponentiation.

▍ Méthode Array.prototype.includes ()


La méthode Array.prototype.includes() est conçue pour vérifier la présence d'un élément dans le tableau. Trouver le désiré dans le tableau, il retourne true , ne trouvant pas - false . Avant ES7, la méthode indexOf() était utilisée pour effectuer la même opération, qui retourne, si un élément est trouvé, le premier index par lequel il peut être trouvé dans le tableau. Si indexOf() ne trouve pas l'élément, il renvoie le nombre -1 .

Selon les règles de conversion de type JavaScript, le nombre -1 converti en true . Par conséquent, pour vérifier les résultats de l'opération d' indexOf() il faut utiliser une construction pas particulièrement pratique de la forme suivante.

 if ([1,2].indexOf(3) === -1) { console.log('Not found') } 

Si dans une situation similaire, en supposant que indexOf() , sans trouver d'élément, renvoie false , utilisez quelque chose comme celui illustré ci-dessous, le code ne fonctionnera pas correctement.

 if (![1,2].indexOf(3)) { // console.log('Not found') } 

Dans ce cas, il s'avère que la construction ![1,2].indexOf(3) donne false .

En utilisant la méthode includes() , ces comparaisons semblent beaucoup plus logiques.

 if (![1,2].includes(3)) { console.log('Not found') } 

Dans ce cas, la construction [1,2].includes(3) renvoie false , cette valeur est un opérateur ! devient true et la console reçoit un message indiquant que l'élément dans le tableau est introuvable.

▍ opérateur d'exponentiation


L'opérateur d'exponentiation remplit la même fonction que la méthode Math.pow() , mais il est plus pratique de l'utiliser qu'une fonction de bibliothèque, car elle fait partie du langage.

 Math.pow(4, 2) == 4 ** 2 //true 

Cet opérateur peut être considéré comme un ajout agréable à JS, qui est utile dans les applications qui effectuent certains calculs. Un opérateur similaire existe dans d'autres langages de programmation.

Norme ES8


La norme ES8 (ES2017) a été publiée en 2017. Comme ES7, il n'a pas apporté grand-chose à la langue. À savoir, nous parlons des fonctionnalités suivantes:

  • Ajout de chaînes à une longueur donnée.
  • Méthode Object.values() .
  • Méthode Object.entries() .
  • Méthode Object.getOwnPropertyDescriptors() .
  • Virgules de fin dans les paramètres de fonction.
  • Fonctions asynchrones.
  • Travaillez avec la mémoire partagée et les opérations atomiques.

▍Ajout de lignes à une longueur donnée


ES8 a introduit deux nouvelles méthodes d'objet String - padStart() et padEnd() .

La méthode padStart() remplit la ligne actuelle avec une autre ligne jusqu'à ce que la ligne finale atteigne la longueur souhaitée. Le remplissage a lieu au début de la ligne (à gauche). Voici comment utiliser cette méthode.

 str.padStart(targetLength [, padString]) 

Ici str est la ligne actuelle, targetLength est la longueur de la ligne finale (si elle est inférieure à la longueur de la ligne actuelle, cette ligne sera renvoyée sans modifications), padString est un paramètre facultatif - la ligne utilisée pour remplir la ligne actuelle. Si padString pas spécifié, un caractère espace est utilisé pour padString ligne actuelle à la longueur spécifiée.

La méthode padEnd() est similaire à padStart() , mais la ligne est remplie à droite.

Considérez des exemples d'utilisation de ces méthodes.

 const str = 'test'.padStart(10) const str1 = 'test'.padEnd(10,'*') console.log(`'${str}'`) //'      test' console.log(`'${str1}'`) //'test******' 

Ici, lorsque vous utilisez padStart() avec uniquement la longueur souhaitée de la chaîne résultante, des espaces ont été ajoutés au début de la chaîne d'origine. Lorsque vous utilisez padEnd() avec la longueur de la ligne finale et la ligne pour la remplir, les caractères * ont été ajoutés à la fin de la ligne d'origine.

▍ Méthode Object.values ​​()


Cette méthode renvoie un tableau contenant les valeurs des propriétés de l'objet, c'est-à-dire les propriétés que l'objet lui-même contient, et non celles qui lui sont accessibles via la chaîne de prototype.

Voici comment l'utiliser.

 const person = { name: 'Fred', age: 87 } const personValues = Object.values(person) console.log(personValues) // ['Fred', 87] 

Cette méthode s'applique également aux tableaux.

▍ Méthode Object.entries ()


Cette méthode renvoie un tableau, dont chaque élément est également un tableau contenant, au format [key, value] , les clés et les valeurs des propres propriétés de l’objet.

 const person = { name: 'Fred', age: 87 } const personValues = Object.entries(person) console.log(personValues) // [['name', 'Fred'], ['age', 87]] 

Lors de l'application de cette méthode aux tableaux, les indices des éléments sont affichés sous forme de clés et ce qui est stocké dans le tableau aux indices correspondants est affiché sous forme de valeurs.

▍ méthode getOwnPropertyDescriptors ()


Cette méthode renvoie des informations sur toutes les propriétés de l'objet. Les ensembles d'attributs (descripteurs) sont associés aux propriétés des objets. En particulier, nous parlons des attributs suivants:

  • value - la valeur de la propriété de l'objet.
  • writable - contient true si la propriété peut être modifiée.
  • get - contient une fonction getter associée à la propriété ou, en l'absence d'une telle fonction, undefined .
  • set - contient la fonction de set de la propriété ou undefined .
  • configurable - si elle est false - la propriété ne peut pas être supprimée, ses attributs ne peuvent pas être modifiés à l'exception de la valeur.
  • enumerable - si true est contenu dans cette propriété - la est énumérable.

Voici comment utiliser cette méthode.

 Object.getOwnPropertyDescriptors(obj) 

Il prend un objet dont vous devez connaître les informations de propriété et renvoie un objet contenant ces informations.

 const person = { name: 'Fred', age: 87 } const propDescr = Object.getOwnPropertyDescriptors(person) console.log(propDescr) /* { name:  { value: 'Fred',    writable: true,    enumerable: true,    configurable: true }, age:  { value: 87,    writable: true,    enumerable: true,    configurable: true } } */ 

Pourquoi cette méthode est-elle nécessaire? Le fait est qu'il vous permet de créer de petites copies d'objets, en copiant, en plus d'autres propriétés, des getters et des setters. Cela ne pouvait pas être fait en utilisant la méthode Object.assign() , qui apparaissait dans la norme ES6, pour copier des objets.

L'exemple suivant a un objet avec un setter qui affiche, à l'aide de console.log() , ce qu'ils essaient d'écrire dans sa propriété correspondante.

 const person1 = { set name(newName) {     console.log(newName) } } person1.name = 'x' // x 

Essayons de copier cet objet en utilisant la méthode assign() .

 const person2 = {} Object.assign(person2, person1) person2.name = 'x' //     ,    

Comme vous pouvez le voir, cette approche ne fonctionne pas. La propriété name , qui était le setter dans l'objet d'origine, est maintenant représentée comme une propriété régulière.

Nous allons maintenant copier l'objet en utilisant les méthodes Object.defineProperties() (il est apparu dans ES5.1) et Object.getOwnPropertyDescriptors() .

 const person3 = {} Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1)) person3.name = 'x' //x 

Ici, le setter reste dans la copie de l'objet.

Il convient de noter que les restrictions spécifiques à Object.assign() sont également caractéristiques de la méthode Object.create() lorsqu'elle est utilisée pour cloner des objets.

▍ Virgules de complétion dans les paramètres de fonction


Cette fonctionnalité vous permet de laisser une virgule à la fin de la liste des paramètres ou arguments, respectivement, lors de la déclaration et lors de l'appel de fonctions.

 const doSomething = ( var1, var2, ) => { //... } doSomething( 'test1', 'test2', ) 

Cela améliore la convivialité des systèmes de contrôle de version. A savoir, nous parlons du fait que lors de l'ajout de nouveaux paramètres à une fonction, vous n'avez pas à modifier le code existant juste pour le plaisir d'insérer une virgule.

▍ Fonctions asynchrones


La construction async/await est apparue dans la norme ES2017, qui peut être considérée comme l'innovation la plus importante de cette version du langage.

Les fonctions asynchrones sont une combinaison de promesses et de générateurs; elles simplifient les constructions qui nécessitaient auparavant une grande quantité de code modèle et des chaînes de promesses peu pratiques à décrire. En fait, nous parlons d'une abstraction de haut niveau sur les promesses.

Lorsque des promesses sont apparues dans la norme ES2015, elles ont été conçues pour résoudre les problèmes existants avec le code asynchrone, ce qu'elles ont fait. Mais au cours des deux années qui ont partagé les normes ES2015 et ES2017, il est devenu clair que les promesses ne peuvent pas être considérées comme la solution finale à ces problèmes.

En particulier, les promesses visaient à résoudre le problème de «l'enfer de rappel», mais, ayant résolu ce problème, elles-mêmes n'ont pas montré leur meilleur côté en raison de la complexité du code dans lequel elles sont utilisées. En fait, la construction async/await résout le problème des promesses et améliore l'utilisabilité du code asynchrone.

Prenons un exemple.

 function doSomethingAsync() { return new Promise((resolve) => {     setTimeout(() => resolve('I did something'), 3000) }) } async function doSomething() { console.log(await doSomethingAsync()) } console.log('Before') doSomething() console.log('After') 

Ce code affichera les éléments suivants sur la console.

 Before After I did something 

Comme vous pouvez le voir, après avoir appelé doSomething() programme continue de s'exécuter, après Before , After s'affiche dans la console, et après trois secondes, I did something .

Appel de fonction asynchrone série


Si nécessaire, les fonctions asynchrones peuvent former quelque chose comme des chaînes d'appels. De tels designs se distinguent par une meilleure lisibilité que quelque chose de similaire, basé uniquement sur des promesses. Cela peut être vu dans l'exemple suivant.

 function promiseToDoSomething() { return new Promise((resolve)=>{     setTimeout(() => resolve('I did something'), 10000) }) } async function watchOverSomeoneDoingSomething() { const something = await promiseToDoSomething() return something + ' and I watched' } async function watchOverSomeoneWatchingSomeoneDoingSomething() { const something = await watchOverSomeoneDoingSomething() return something + ' and I watched as well' } watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => { console.log(res) // I did something and I watched and I watched as well }) 

▍ Mémoire partagée et opérations atomiques


Nous parlons ici de l'objet SharedArrayBuffer , qui vous permet de décrire les zones de mémoire partagée, et de l'objet Atomics , qui contient un ensemble d'opérations atomiques sous la forme de méthodes statiques. Des détails sur les possibilités que ces objets offrent au programmeur peuvent être trouvés ici .

Norme ES9


ES9 (ES2018) est la dernière version de la norme au moment de la publication de ce document. Voici ses principales caractéristiques:

  • Appliquez des instructions d'étalement et de repos aux objets.
  • Itérateurs asynchrones.
  • Méthode Promise.prototype.finally() .
  • Améliorations des expressions régulières.

▍Application des opérateurs d'étalement et de repos aux objets


Nous avons déjà parlé des opérateurs de repos et de propagation qui sont apparus dans ES6 et peuvent être utilisés pour travailler avec des tableaux. Les deux ressemblent à trois points. L'opérateur reste, dans l'exemple suivant de déstructuration d'un tableau, vous permet de placer ses premier et deuxième éléments dans les constantes first et second , et tout le reste dans les others constants.

 const numbers = [1, 2, 3, 4, 5] const [first, second, ...others] = numbers console.log(first) //1 console.log(second) //2 console.log(others) //[ 3, 4, 5 ] 

L'opérateur d' spread vous permet de passer des tableaux à des fonctions qui attendent des listes de paramètres régulières.

 const numbers = [1, 2, 3, 4, 5] const sum = (a, b, c, d, e) => a + b + c + d + e const res = sum(...numbers) console.log(res) //15 

Maintenant, en utilisant la même approche, vous pouvez travailler avec des objets. Voici un exemple d'utilisation de l'instruction rest dans une opération d'affectation destructrice.

 const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } console.log(first) //1 console.log(second) //2 console.log(others) //{ third: 3, fourth: 4, fifth: 5 } 

Voici l'instruction spread utilisée lors de la création d'un nouvel objet basé sur un objet existant. Cet exemple continue le précédent.

 const items = { first, second, ...others } console.log(items) //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } 

▍ Itérateurs asynchrones


La nouvelle construction for-await-of vous permet d'appeler des fonctions asynchrones qui renvoient des promesses en boucles. Ces boucles attendent la résolution de la promesse avant de passer à l'étape suivante. Voici à quoi ça ressemble.

 for await (const line of readLines(filePath)) { console.log(line) } 

Dans le même temps, il convient de noter que ces boucles doivent être utilisées dans les fonctions asynchrones - de la même manière que lorsque vous travaillez avec la construction async/await .

▍ Méthode Promise.prototype.finally ()


Si la promesse est résolue avec succès, la méthode then() est appelée. En cas de problème, la méthode catch() est appelée. La méthode finally() vous permet d'exécuter du code indépendamment de ce qui s'est passé auparavant.

 fetch('file.json') .then(data => data.json()) .catch(error => console.error(error)) .finally(() => console.log('finished')) 

▍ Améliorations de l'expression régulière


Les expressions régulières ont la capacité de vérifier rétrospectivement les chaînes ( ?<= ). Cela vous permet de rechercher certaines constructions dans les lignes devant lesquelles il y a d'autres constructions.

La possibilité de précéder les vérifications à l'aide de la construction ?= Était présente dans les expressions régulières implémentées en JavaScript avant la norme ES2018. Ces vérifications vous permettent de savoir si un autre fragment suit un certain fragment d'une ligne.

 const r = /Roger(?= Waters)/ const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //false console.log(res2) //true 

Construction ?! effectue l'opération inverse - une correspondance ne sera trouvée que si une autre ligne ne suit pas la ligne donnée.

 const r = /Roger(?! Waters)/g const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //true console.log(res2) //false 

En vérification rétrospective, comme déjà mentionné, la construction ?<= utilisée.

 const r = /(?<=Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //false console.log(res2) //true 

L'opération opposée à celle décrite peut être effectuée en utilisant la construction ?<! .

 const r = /(?<!Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //true console.log(res2) //false 

Séquences d'échappement regex Unicode


Dans les expressions régulières, vous pouvez utiliser la classe \d qui correspond à n'importe quel chiffre, la classe \s qui correspond à n'importe quel caractère d'espacement, la classe \w qui correspond à n'importe quel caractère alphanumérique, etc. La fonctionnalité en question étend l'ensemble des classes qui peuvent être utilisées dans les expressions régulières, vous permettant de travailler avec des séquences Unicode. Nous parlons de la classe \p{} et de l'inverse de la classe \P{} .

En Unicode, chaque caractère possède un ensemble de propriétés. Ces propriétés sont indiquées entre accolades du groupe \p{} . Ainsi, par exemple, la propriété Script détermine la famille de langues à laquelle appartient un caractère, la propriété ASCII , logique, prend la valeur true pour les caractères ASCII, etc. Par exemple, nous verrons si certaines lignes ne contiennent que des caractères ASCII.

 console.log(r.test('abc')) //true console.log(r.test('ABC@')) //true console.log(r.test('ABC')) //false 

La propriété ASCII_Hex_Digit n'est true que pour les caractères pouvant être utilisés pour écrire des nombres hexadécimaux.

 const r = /^\p{ASCII_Hex_Digit}+$/u console.log(r.test('0123456789ABCDEF')) //true console.log(r.test('H')) //false 

Il existe de nombreuses autres propriétés similaires qui sont utilisées de la même manière que celle décrite ci-dessus. Parmi eux, les Uppercase , les Lowercase , l' White_Space , l' Alphabetic et les Emoji .

Par exemple, voici comment utiliser la propriété Script pour déterminer quel alphabet est utilisé dans une chaîne. Ici, nous vérifions la chaîne pour l'utilisation de l'alphabet grec.

 const r = /^\p{Script=Greek}+$/u console.log(r.test('ελληνικά')) //true console.log(r.test('hey')) //false 

Les détails sur ces propriétés peuvent être trouvés ici .

Groupes nommés


Les groupes de caractères capturés dans ES2018 peuvent recevoir des noms. Voici à quoi ça ressemble.

 const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ const result = re.exec('2015-01-02') console.log(result) /* [ '2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: { year: '2015', month: '01', day: '02' } ] */ 

Sans l'utilisation de groupes nommés, les mêmes données ne seraient disponibles que sous forme d'éléments de tableau.

 const re = /(\d{4})-(\d{2})-(\d{2})/ const result = re.exec('2015-01-02') console.log(result) /* [ '2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: undefined ] */ 

Drapeau regex s


L'utilisation du drapeau s donne un caractère . (point) correspondra, entre autres, au caractère de nouvelle ligne. Sans ce drapeau, un point correspond à n'importe quel caractère à l'exception d'une nouvelle ligne.

 console.log(/hi.welcome/.test('hi\nwelcome')) // false console.log(/hi.welcome/s.test('hi\nwelcome')) // true 

Résumé


Avec ce matériel, nous terminons la publication des traductions de ce manuel JavaScript. Nous espérons que ces publications ont aidé ceux qui n'avaient pas travaillé avec JavaScript avant de faire leurs premiers pas dans la programmation dans ce langage.

Chers lecteurs! Si vous n'avez pas encore écrit en JS et maîtrisé cette langue dans ce guide, veuillez partager vos impressions.

Source: https://habr.com/ru/post/fr431872/


All Articles