EcmaScript 10 - JavaScript de cette année (ES2019)

La normalisation JS est passée à un cycle de mise à jour d'un an, et le début de l'année est le moment idéal pour découvrir ce qui nous attend à l'anniversaire - la dixiÚme édition d'EcmaScript!


ES 9 est la version actuelle de la spécification .


ES 10 est encore un projet .


À ce jour, l' Ă©tape 4 # n'a que quelques suggestions.


Et à l' étape 3 # - une douzaine entiÚre!


Parmi ceux-ci, à mon avis, les plus intéressants sont les champs privés des classes # , la grammaire shebang pour les scripts # , les nombres de précision arbitraire # , l' accÚs au contexte global # et les importations dynamiques # .



KDPV: aimant jaune avec l'inscription "JS ES10" sur l'écran du moniteur - de kasper.green & elfafeya.art
Photo de: kasper.green; Aimant jaune: elfafeya.art & kasper.green


Table des matiĂšres


Cinq étapes #


Étape 4 - Final #


‱ catch - l'argument est devenu facultatif # ;


‱ Symbol().description - accesseur de la description du symbole # ;


‱ ' EcmaScript' - compatibilitĂ© amĂ©liorĂ©e avec le format JSON # ;


‱ .toString() - mĂ©thode prototype mise Ă  jour # .


‱ Object.fromEntries() - crĂ©ation d'un objet Ă  partir d'un tableau de paires - clĂ© \ valeur # ;


‱ .flat() et .flatMap() sont des mĂ©thodes prototype de tableau .




Étape 3 - PrĂ©-version #


‱ # - tout est privĂ© dans les classes, via octotorp # ;


‱ #!/usr/bin/env node - grammaire shebang pour les scripts # ;


‱ BigInt() - une nouvelle primitive, pour les nombres de prĂ©cision arbitraires # ;


‱ globalThis - une nouvelle façon d'accĂ©der au contexte mondial # ;


‱ import(dynamic) - importation dynamique # ;


‱ import.meta - mĂ©ta-informations sur le module chargĂ© # ;


‱ JSON.stringify() - correction de la mĂ©thode # ;


‱ RegExp - fonctionnalitĂ©s obsolĂštes # ;


‱ .trimStart() et .trimEnd() - mĂ©thodes de chaĂźne de prototype # ;


‱ .matchAll() - .match() avec l'indicateur global # ;


Résultats #




Cinq étapes


Étape 0 ↓ Strawman Basting Une idĂ©e qui peut ĂȘtre implĂ©mentĂ©e via le plugin Babel .


Étape 1 ↓ Proposition Proposition VĂ©rification de la viabilitĂ© de l'idĂ©e.


Étape 2 ↓ Projet de projet DĂ©but du dĂ©veloppement des spĂ©cifications.


Étape 3 ↓ SpĂ©cification de l'aperçu du candidat .;


Étape 4 ֍ TerminĂ© La version finale des spĂ©cifications pour cette annĂ©e est terminĂ©e.




Nous ne considérerons que l' étape 4 - la norme de facto.


Et l' étape 3 - qui est sur le point d'en faire partie.





֍ Étape 4


Ces modifications sont déjà standard.


Argument facultatif pour catch


https://github.com/tc39/proposal-optional-catch-binding


Avant ES 10, le catch nĂ©cessitait un argument requis pour collecter les informations d'erreur, mĂȘme s'il n'Ă©tait pas utilisĂ©:


 function isValidJSON(text) { try { JSON.parse(text); return true; } catch(unusedVariable) { //    return false; } } 


Edge n'a pas encore été mis à niveau vers ES 10 et devrait se bloquer avec une erreur.


À partir de l'Ă©dition ES 10, les parenthĂšses peuvent ĂȘtre omises et la catch deviendra comme deux gouttes d'eau comme try .



Mon Chrome a déjà été mis à jour vers ES 10 et, à certains endroits, vers Stage 3 . D'autres captures d'écran proviendront de Chrome


code source
 function isValidJSON(text) { try { JSON.parse(text); return true; } catch { //   return false; } } 



Accéder aux descriptions des liens symboliques


https://tc39.imtqy.com/proposal-Symbol-description/


Une description de lien symbolique peut ĂȘtre obtenue indirectement en utilisant la mĂ©thode toString ():


 const symbol_link = Symbol("Symbol description") String(symbol_link) // "Symbol(Symbol description)" 

À partir d' ES 10, les caractĂšres ont une propriĂ©tĂ© de description en lecture seule. Il vous permet d'obtenir une description du symbole sans aucune danse avec un tambourin:


 symbol_link.description // "Symbol description" 

Si la description n'est pas spécifiée, elle renverra - undefined :


 const without_description_symbol_link = Symbol() without_description_symbol_link.description // undefined const empty_description_symbol_link = Symbol('') empty_description_symbol_link.description // "" 



ChaĂźnes EcmaScript compatibles avec JSON


https://github.com/tc39/proposal-json-superset


EcmaScript, avant sa dixiÚme édition, prétend que JSON est un sous-ensemble de JSON.parse , mais ce n'est pas vrai.


Les lignes JSON peuvent contenir des sĂ©parateurs de lignes non blindĂ©s U+2028 SÉPARATEUR DE LIGNE et les paragraphes U+2029 SÉPARATEUR DE PARAGRAPHE .


ECMAScript s'aligne jusqu'Ă  la dixiĂšme version - no.


Si vous appelez eval() dans Edge avec la chaĂźne "\u2029" ,
il se comporte comme si nous faisions un saut de ligne - en plein milieu du code:




Avec les lignes ES 10 - tout va bien:





Raffinement du prototype de la méthode .toString()


http://tc39.imtqy.com/Function-prototype-toString-revision/


Changer les objectifs
  • supprimer l'exigence incompatible en amont:

Si l'implémentation ne peut pas créer une chaßne de code source répondant à ces critÚres, elle doit renvoyer une chaßne pour laquelle eval lÚvera une exception avec une erreur de syntaxe.

  • clarifier une exigence «fonctionnellement Ă©quivalente»;


  • normaliser la reprĂ©sentation sous forme de chaĂźne des fonctions intĂ©grĂ©es et des objets hĂŽtes;


  • clarifier les exigences de prĂ©sentation en fonction des «caractĂ©ristiques rĂ©elles» d'un objet;


  • assurez-vous que l'analyse de la chaĂźne contient le mĂȘme corps de fonction et la mĂȘme liste de paramĂštres que l'original;


  • pour les fonctions dĂ©finies Ă  l'aide du code ECMAScript, toString doit renvoyer un fragment du texte source du dĂ©but du premier jeton Ă  la fin du dernier jeton correspondant Ă  la construction grammaticale correspondante;


  • pour les objets fonctionnels intĂ©grĂ©s, toString ne doit renvoyer rien d'autre qu'une NativeFunction;


  • pour les objets appelĂ©s qui n'ont pas Ă©tĂ© dĂ©finis Ă  l'aide du code ECMAScript, toString doit renvoyer un NativeFunction;


  • pour les fonctions créées dynamiquement (constructeurs de fonctions ou gĂ©nĂ©rateurs), toString doit synthĂ©tiser le texte source;


  • pour tous les autres objets, toString doit lever une exception TypeError.



 //   function () { console.log('My Function!'); }.toString(); // function () { console.log('My Function!'); } //     Number.parseInt.toString(); // function parseInt() { [native code] } //     function () { }.bind(0).toString(); // function () { [native code] } //     Symbol.toString(); // function Symbol() { [native code] } //     Function().toString(); // function anonymous() {} //    - function* () { }.toString(); // function* () { } // .call   ,   ,  Function.prototype.toString.call({}); // Function.prototype.toString requires that 'this' be a Function" 



Création d'un objet à l'aide de la méthode Object.fromEntries()


https://github.com/tc39/proposal-object-from-entries


fonctionne en chrome


Analogue de _.fromPairs de lodash :


 Object.fromEntries([['key_1', 1], ['key_2', 2]]) // {key_1: 1; key_2: 2} 



Tableaux unidimensionnels avec .flat() et .flatMap()


https://github.com/tc39/proposal-flatMap


fonctionne en chrome


La baie a acquis les prototypes .flat() et .flatMap() , qui sont généralement similaires aux implémentations lodash , mais présentent encore quelques différences. Argument facultatif - définit la profondeur de traversée maximale de l'arbre:


 const deep_deep_array = [ '≄0 —  ', [ '≄1 —  ', [ '≄2 —  ', [ '≄3 —  ', [ '≄4 —  ' ] ] ] ] ] // 0 —     deep_deep_array.flat(0) //  ["≄0 —  ", Array(2)] // 1 —    deep_deep_array.flat() //  [" ", " ", Array(2)] deep_deep_array.flat(2) //  [" ", " ", " ", Array(2)] deep_deep_array.flat(100500) // [" ", " ", " ", " ", " "] 

.flatMap() équivaut à appeler consécutivement .map().flat() . La fonction de rappel passée à la méthode doit renvoyer un tableau qui fera partie d'un tableau plat commun:


 ['Hello', 'World'].flatMap(word => [...word]) // ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"] 

En utilisant uniquement .flat() et .map() , l'exemple peut ĂȘtre réécrit comme ceci:


  ['Hello', 'World'].map(word => [...word]).flat() // ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"] 

Notez également que .flatMap() , contrairement à .flat() n'a pas de paramÚtres de profondeur d'analyse. Donc seul le premier niveau sera collé.







֍ Étape 3


Propositions issues du projet de statut mais non encore entrées dans la version finale de la norme.


Privé \ statique \ méthodes publiques \ propriétés \ attributs des classes


https://github.com/tc39/proposal-class-fields
https://github.com/tc39/proposal-private-methods
https://github.com/tc39/proposal-static-class-features


Dans certaines langues, il existe un accord pour appeler des mĂ©thodes privĂ©es avec un espace visible (" _ " - une telle piĂšce, vous connaissez peut-ĂȘtre ce signe sous le mauvais nom - soulignement) .


Par exemple, comme ceci:


 <?php class AdultContent { private $_age = 0; private $_content = '
is dummy example content (‱)(‱) —3 (.)(.) only for adults
'; function __construct($age) { $this->_age = $age; } function __get($name) { if($name === 'content') { return " (age: ".$this->_age.") → ".$this->_getContent()."\r\n"; } else { return 'without info'; } } private function _getContent() { if($this->_contentIsAllowed()) { return $this->_content; } return 'Sorry. Content not for you.'; } private function _contentIsAllowed() { return $this->_age >= 18; } function __toString() { return $this->content; } } echo "<pre>"; echo strval(new AdultContent(10)); // (age: 10) → Sorry. Content not for you echo strval(new AdultContent(25)); // (age: 25) → 
is dummy example content (‱)(‱) —3 only for adults
 $ObjectAdultContent = new AdultContent(32); echo $ObjectAdultContent->content; // (age: 32) → 
is dummy example content (‱)(‱) —3 only for adults
 ?> 

Permettez-moi de vous rappeler - ce n'est qu'un accord. Rien n'empĂȘche d'utiliser le prĂ©fixe Ă  d'autres fins, d'utiliser un prĂ©fixe diffĂ©rent ou de ne pas l'utiliser du tout.


Personnellement, je suis impressionnĂ© par l'idĂ©e d'utiliser un espace visible comme prĂ©fixe pour les fonctions qui retournent this . Ils peuvent donc ĂȘtre combinĂ©s en une chaĂźne d'appels.


Les développeurs de la spécification EcmaScript sont allés plus loin et ont intégré le préfixe- octotorp (« # » - réseau, hachage) à la syntaxe.


L'exemple prĂ©cĂ©dent sur ES 10 peut ĂȘtre réécrit comme suit:


 export default class AdultContent { //    #age = 0 #adult_content = '
is dummy example content (‱)(‱) —3 (.)(.) only for adults
' constructor(age) { this.#setAge(age) } //    static #userIsAdult(age) { return age > 18 } //   get content () { return `(age: ${this.#age}) → ` + this.#allowed_content } //   get #allowed_content() { if(AdultContent.userIsAdult(this.age)){ return this.#adult_content } else { return 'Sorry. Content not for you.' } } //   #setAge(age) { this.#age = age } toString () { return this.#content } } const AdultContentForKid = new AdultContent(10) console.log(String(AdultContentForKid)) // (age: 10) → Sorry. Content not for you. console.log(AdultContentForKid.content) // (age: 10) → Sorry. Content not for you. const AdultContentForAdult = new AdultContent(25) console.log(String(AdultContentForAdult)) // (age: 25) → 
is dummy example content (‱)(‱) —3 (.)(.) only for adults
 console.log(AdultContentForAdult.content) // (age: 25) → 
is dummy example content (‱)(‱) —3 (.)(.) only for adults
 

L'exemple est inutilement compliquĂ© pour dĂ©montrer les propriĂ©tĂ©s, mĂ©thodes et attributs privĂ©s Ă  la fois. Mais en gĂ©nĂ©ral, JS - plaĂźt Ă  l'Ɠil par sa concision par rapport Ă  la version PHP. Pas de fonction privĂ©e _... pour vous, pas de point-virgule en fin de ligne, et un point au lieu de "->" pour aller plus loin dans l'objet.


Getters nommés. Pour les noms dynamiques, les objets proxy.


Cela semble ĂȘtre des bagatelles, mais aprĂšs le passage Ă  JS, il y a de moins en moins de dĂ©sir de revenir Ă  PHP.


Soit dit en passant, les accesseurs privés sont disponibles uniquement avec Babel 7.3.0 et versions ultérieures.


Au moment d'écrire ces lignes, la version la plus récente de npmjs.com est 7.2.2


Au plaisir de l'étape 4!




Shebang Grammar


https://github.com/tc39/proposal-hashbang


Hashbang est un moyen pour Unix de spécifier un interpréteur pour un fichier exécutable:


 #!/usr/bin/env node //   'use strict'; console.log(1); 

 #!/usr/bin/env node //   export {}; console.log(1); 

Chrome lance SyntaxError: Invalid or&nbsp;unexpected token un SyntaxError: Invalid or&nbsp;unexpected token sur un SyntaxError: Invalid or&nbsp;unexpected token similaire


Grands chiffres avec BigInt


https://github.com/tc39/proposal-bigint


prise en charge du navigateur

Prise en charge du navigateur pour la primitive BigInt ()


Entier maximal pouvant ĂȘtre utilisĂ© en toute sĂ©curitĂ© en JavaScript (2⁔³ - 1):


 console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991 

BigInt est nécessaire pour utiliser des nombres de précision arbitraires.


Ce type est déclaré de plusieurs maniÚres:


 //  'n'       910000000000000100500n // 910000000000000100500n //      BigInt()   BigInt( 910000000000000200500 ) // 910000000000000200500n //     -  BigInt( "910000000000000300500" ) // 910000000000000300500n //      1642  BigInt( "" ) \\ 

Il s'agit d'un nouveau type primitif:


 typeof 123; // → 'number' typeof 123n; // → 'bigint' 

Il peut ĂȘtre comparĂ© aux nombres ordinaires:


 42n === BigInt(42); // → true 42n == 42; // → true 

Mais les opĂ©rations mathĂ©matiques doivent ĂȘtre effectuĂ©es dans un seul type:


 20000000000000n/20n // 1000000000000n 20000000000000n/20 // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions 

Unaire moins est pris en charge, unaire plus renvoie une erreur:


  -2n // -2n +2n // Uncaught TypeError: Cannot convert a BigInt value to a number 


globalThis - une nouvelle façon d'accéder au contexte mondial


https://github.com/tc39/proposal-global


fonctionne en chrome


Étant donnĂ© que les implĂ©mentations de portĂ©e globale dĂ©pendent d'un moteur particulier, vous avez dĂ» faire quelque chose comme ceci avant:


 var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); }; 

Et mĂȘme cette option ne garantissait pas que tout fonctionnerait Ă  coup sĂ»r.


globalThis C'est un moyen commun pour toutes les plateformes d'accéder à la portée mondiale:


 //      globalThis.Array(1,2,3) // [1, 2, 3] //        globalThis.myGLobalSettings = { it_is_cool: true } //        globalThis.myGLobalSettings // {it_is_cool: true} 



import(dynamic)


https://github.com/tc39/proposal-dynamic-import


prise en charge du navigateur

Prise en charge du navigateur pour les importations dynamiques


Je voulais des variables dans les lignes d'importation Avec les importations dynamiques, cela est devenu possible:


 import(`./language-packs/${navigator.language}.js`) 

L'importation dynamique est une opération asynchrone. Renvoie une promesse qui, aprÚs avoir chargé le module, le renvoie à la fonction de rappel.


Par conséquent, vous pouvez charger des modules - différés si nécessaire:


 element.addEventListener('click', async () => { //   await    const module = await import(`./events_scripts/supperButtonClickEvent.js`) module.clickEvent() }) 

Syntaxiquement, cela ressemble à un appel à la fonction import() , mais n'hérite pas de Function.prototype , ce qui signifie qu'il ne réussira pas à appeler par call ou à apply :


 import.call("example this", "argument") // Uncaught SyntaxError: Unexpected identifier 



import.meta - méta-informations sur le module chargé.


https://github.com/tc39/proposal-import-meta


fonctionne en chrome


Dans le code du module chargé, il est devenu possible d'obtenir des informations à ce sujet. Maintenant, ce n'est que l'adresse à laquelle le module a été chargé:


 console.log(import.meta); // { url: "file:///home/user/my-module.js" } 



JSON.stringify() méthode JSON.stringify()


https://github.com/tc39/proposal-well-formed-stringify


La section 8.1 de la RFC 8259 exige que le texte JSON échangé en dehors d'un écosystÚme fermé soit codé en utilisant UTF-8, mais JSON.stringify peut renvoyer des chaßnes contenant des points de code qui ne sont pas représentés dans UTF-8 (en particulier, les points de code de substitution de U + D800 à U + DFFF)


Ainsi, la ligne \uDF06\uD834 aprĂšs le traitement de JSON.stringify () se transforme en \\udf06\\ud834 :


 /*         */ JSON.stringify('\uDF06\uD834') '"\\udf06\\ud834"' JSON.stringify('\uDEAD') '"\\udead"' 

Cela ne devrait pas ĂȘtre le cas, et la nouvelle spĂ©cification corrige cela. Edge et Chrome ont dĂ©jĂ  Ă©tĂ© mis Ă  jour.




Fonctionnalités RegExp obsolÚtes


https://github.com/tc39/proposal-regexp-legacy-features


Spécification des fonctions RegExp héritées, telles que la méthode RegExp.$1 et RegExp.prototype.compile() .




Méthodes de chaßne de prototype .trimStart() et .trimEnd()


https://github.com/tc39/proposal-string-left-right-trim


fonctionne en chrome


Par analogie avec les méthodes .padStart() et .padEnd() , coupez les espaces au début et à la fin de la ligne, respectivement:


 const one = " hello and let "; const two = "us begin. "; console.log( one.trimStart() + two.trimEnd() ) // "hello and let us begin." 



.matchAll () est une nouvelle méthode de chaßne prototype.


https://github.com/tc39/proposal-string-matchall


fonctionne en chrome


Fonctionne comme la méthode .match() avec le drapeau g activé, mais renvoie un itérateur:


 const string_for_searh = 'olololo' //         string_for_searh.match(/o/) // ["o", index: 0, input: "olololo", groups: undefined] //       string_for_searh.match(/o/g) // ["o", "o", "o", "o"] //   string_for_searh.matchAll(/o/) // {_r: /o/g, _s: "olololo"} //        , //      .match    for(const item of string_for_searh.matchAll(/o/)) { console.log(item) } // ["o", index: 0, input: "olololo", groups: undefined] // ["o", index: 2, input: "olololo", groups: undefined] // ["o", index: 4, input: "olololo", groups: undefined] // ["o", index: 6, input: "olololo", groups: undefined] 

L'argument doit ĂȘtre une expression rĂ©guliĂšre, sinon une exception sera levĂ©e:


 'olololo'.matchAll('o') // Uncaught TypeError: o is not a regexp! 







Résumé


L'Ă©tape 4 a apportĂ© plus de changements cosmĂ©tiques. L'intĂ©rĂȘt est l' Ă©tape 3 . La plupart des suggestions dans Chrome sont dĂ©jĂ  implĂ©mentĂ©es et les propriĂ©tĂ©s des objets sont vraiment tournĂ©es vers l'avenir.






Corrections dans l'article



Si vous avez remarquĂ© une inexactitude dans l'article, une erreur ou s'il y a quelque chose Ă  complĂ©ter, vous pouvez m'Ă©crire un message personnel , mais il vaut mieux utiliser le rĂ©fĂ©rentiel d'articles https://github.com/KasperGreen/es10 vous-mĂȘme. Pour contribution active, je dĂ©cernerai une mĂ©daille magnĂ©tique jaune avec KDPV.


Matériel connexe


Matériel en anglais Version actuelle de la norme Ecma-262


Matériel en anglais Projet de la prochaine version de la norme Ecma-262


ECMAScript


Nouveaux champs de classe privée en JavaScript


Article sur Habré Présentation des normes ES7, ES8 et ES9


Shebang


Article sur Habré BigInt - longue arithmétique en JavaScript


Article sur Habré Chemin du module JavaScript


Matériel en anglais Pourquoi pas privé x


Article sur Habré Proposition ECMAScript: Array.prototype. {Flat, flatMap}


Champs de cours publics et privés


JavaScript: le grand tout bien pourquoi




UPD (mars):


Changé le statut en Stage - 4 :


‱ .trimStart() et .trimEnd() - mĂ©thodes de chaĂźne de prototype # ;


‱ .matchAll() - .match() avec l'indicateur global # ;


KDPV alternatif avec un aimant jaune de elfafeya.art
Photo de: kasper.green; Aimant jaune: elfafeya.art & kasper.green

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


All Articles