EcmaScript 10 - Das diesjÀhrige JavaScript (ES2019)

Die JS-Standardisierung wurde auf einen einjÀhrigen Aktualisierungszyklus umgestellt, und der Jahresbeginn ist eine gute Zeit, um herauszufinden, was uns zum JubilÀum erwartet - die zehnte Ausgabe von EcmaScript!


ES 9 ist die aktuelle Version der Spezifikation .


ES 10 ist noch ein Entwurf .


Bisher enthÀlt Stage 4 # nur einige VorschlÀge.


Und in Stufe 3 # - ein ganzes Dutzend!


Von diesen sind meiner Meinung nach die interessantesten Klassenfelder # , Shebang-Grammatik fĂŒr Skripte # , Zahlen beliebiger Genauigkeit # , Zugriff auf den globalen Kontext # und dynamische Importe # .



KDPV: Gelber Magnet mit der Aufschrift "JS ES10" auf dem Bildschirm - von kasper.green & elfafeya.art
Foto von: kasper.green; Gelber Magnet: elfafeya.art & kasper.green


Inhalt


FĂŒnf Stufen #


Stufe 4 - Finale #


‱ catch - das Argument ist optional geworden # ;


‱ Symbol().description - Zugriff auf die Beschreibung des Symbols # ;


‱ ' EcmaScript' - verbesserte KompatibilitĂ€t mit dem JSON- Format # ;


‱ .toString() - Prototypmethode aktualisiert # .


‱ Object.fromEntries() - Erstellen eines Objekts aus einem Array von Paaren - key \ value # ;


‱ .flat() und .flatMap() sind Prototyp-Array-Methoden .




Stufe 3 - Pre-Release #


‱ # - alles ist privat im Unterricht, durch octotorp # ;


‱ #!/usr/bin/env node - Shebang-Grammatik fĂŒr Skripte # ;


‱ BigInt() - ein neues BigInt() fĂŒr Zahlen mit beliebiger Genauigkeit # ;


‱ globalThis - eine neue Möglichkeit, auf den globalen Kontext zuzugreifen # ;


‱ import(dynamic) - dynamischer Import # ;


‱ import.meta - Metainformationen ĂŒber das geladene Modul # ;


‱ JSON.stringify() - Korrektur der # -Methode ;


‱ RegExp - veraltete Funktionen # ;


‱ .trimStart() und .trimEnd() - Prototyp-String-Methoden # ;


‱ .matchAll() - .match() mit dem globalen Flag # ;


Ergebnisse #




FĂŒnf Stufen


Stufe 0 ↓ Strawman Basting Eine Idee, die ĂŒber das Babel- Plugin umgesetzt werden kann.


Stufe 1 ↓ Vorschlag Vorschlag ÜberprĂŒfung der Realisierbarkeit der Idee .;


Stufe 2 ↓ Entwurf Entwurf Beginn der Spezifikationsentwicklung .;


Stufe 3 ↓ Spezifikation der Kandidatenvorschau ;


Stufe 4 ֍ Abgeschlossen Die endgĂŒltige Version der Spezifikation fĂŒr dieses Jahr ist abgeschlossen.




Wir werden nur Stufe 4 betrachten - den De-facto-Standard.


Und Stufe 3 - die bald Teil davon wird.





֍ Stufe 4


Diese Änderungen sind bereits Standard.


Optionales Argument zum catch


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


Vor ES 10 benötigte der catch ein erforderliches Argument, um Fehlerinformationen zu sammeln, auch wenn es nicht verwendet wurde:


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


Edge wurde noch nicht auf ES 10 aktualisiert und wird voraussichtlich mit einem Fehler abstĂŒrzen.


Ab der ES 10-Edition können Klammern weggelassen werden, und der catch wird wie beim try zu zwei Wassertropfen.



Mein Chrome wurde bereits auf ES 10 und an einigen Stellen auf Stufe 3 aktualisiert. Weitere Screenshots stammen von Chrome


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



Greifen Sie auf symbolische Linkbeschreibungen zu


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


Eine symbolische Linkbeschreibung kann indirekt mit der toString () -Methode erhalten werden:


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

Ab ES 10 haben Zeichen eine schreibgeschĂŒtzte Beschreibungseigenschaft. Sie können eine Beschreibung des Symbols erhalten, ohne mit einem Tamburin zu tanzen:


 symbol_link.description // "Symbol description" 

Wenn die Beschreibung nicht angegeben wird, wird sie zurĂŒckgegeben - undefined :


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



Mit JSON kompatible EcmaScript-Zeichenfolgen


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


EcmaScript behauptet vor seiner zehnten Ausgabe, dass JSON eine Teilmenge von JSON.parse , aber dies ist nicht wahr.


JSON- Zeilen können ungeschirmte Zeilentrennzeichen U+2028 LINE SEPARATOR und AbsÀtze U+2029 PARAGRAPH SEPARATOR enthalten .


ECMAScript steht bis zur zehnten Version - Nr.


Wenn Sie eval() in Edge mit der Zeichenfolge "\u2029" ,
Es verhÀlt sich so, als hÀtten wir einen Zeilenumbruch gemacht - genau in der Mitte des Codes:




Mit ES 10-Linien ist alles in Ordnung:





Verfeinerung der Prototyp-Methode .toString()


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


Ziele Àndern
  • rĂŒckwĂ€rts inkompatible Anforderung entfernen:

Wenn die Implementierung keine Quellcodezeichenfolge erstellen kann, die diese Kriterien erfĂŒllt, muss sie eine Zeichenfolge zurĂŒckgeben, fĂŒr die eval eine Ausnahme mit einem Syntaxfehler auslöst.

  • eine „funktional Ă€quivalente“ Anforderung klĂ€ren;


  • Standardisieren Sie die Zeichenfolgendarstellung von integrierten Funktionen und Hostobjekten.


  • KlĂ€rung der PrĂ€sentationsanforderungen anhand der „tatsĂ€chlichen Eigenschaften“ eines Objekts;


  • Stellen Sie sicher, dass das Parsen der Zeichenfolge denselben Funktionskörper und dieselbe Parameterliste wie das Original enthĂ€lt.


  • FĂŒr Funktionen, die mit ECMAScript-Code definiert wurden, sollte toString ein Fragment des Quelltextes vom Anfang des ersten Tokens bis zum Ende des letzten Tokens zurĂŒckgeben, das der entsprechenden grammatikalischen Konstruktion entspricht.


  • FĂŒr integrierte Funktionsobjekte sollte toString nur eine NativeFunction zurĂŒckgeben.


  • FĂŒr aufgerufene Objekte, die nicht mit ECMAScript-Code definiert wurden, muss toString eine NativeFunction zurĂŒckgeben.


  • FĂŒr dynamisch erstellte Funktionen (Funktions- oder Generatorkonstruktoren) muss toString den Quelltext synthetisieren.


  • FĂŒr alle anderen Objekte sollte toString eine TypeError-Ausnahme auslösen.



 //   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" 



Erstellen eines Objekts mit der Object.fromEntries() -Methode


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


arbeitet in Chrom


Analog von _.fromPairs from lodash :


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



Eindimensionale Arrays mit .flat() und .flatMap()


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


arbeitet in Chrom


Das Array hat die Prototypen .flat() und .flatMap() , die im Allgemeinen den lodash- Implementierungen Àhnlich sind , jedoch noch einige Unterschiede aufweisen. Optionales Argument - Legt die maximale Baumdurchquerungstiefe fest:


 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() entspricht dem aufeinanderfolgenden Aufruf von .map().flat() . Die an die Methode ĂŒbergebene RĂŒckruffunktion sollte ein Array zurĂŒckgeben, das Teil eines gemeinsamen flachen Arrays wird:


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

Mit nur .flat() und .map() kann das Beispiel folgendermaßen umgeschrieben werden:


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

Beachten Sie auch, dass .flatMap() im Gegensatz zu .flat() keine Einstellungen fĂŒr die .flat() hat. Es wird also nur die erste Ebene geklebt.







֍ Stufe 3


VorschlĂ€ge, die aus dem Entwurfsstatus hervorgegangen sind, aber noch nicht in die endgĂŒltige Fassung des Standards eingegangen sind.


Private \ statische \ öffentliche Methoden \ Eigenschaften \ Attribute von Klassen


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


In einigen Sprachen gibt es eine Vereinbarung, private Methoden mit einem sichtbaren Leerzeichen aufzurufen (" _ " - ein solches StĂŒck, Sie kennen dieses Zeichen möglicherweise unter dem falschen Namen - Unterstrich) .


Zum Beispiel so:


 <?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
 ?> 

Ich möchte Sie daran erinnern, dass dies nur eine Vereinbarung ist. Nichts hindert Sie daran, das PrĂ€fix fĂŒr andere Zwecke zu verwenden, ein anderes PrĂ€fix zu verwenden oder es ĂŒberhaupt nicht zu verwenden.


Persönlich bin ich beeindruckt von der Idee, einen sichtbaren Raum als PrĂ€fix fĂŒr Funktionen zu verwenden, die this . So können sie zu einer Anrufkette zusammengefasst werden.


Die Entwickler der EcmaScript- Spezifikation gingen noch weiter und machten das PrĂ€fix Octotorp („ # “ - Gitter, Hash) Teil der Syntax.


Das vorherige Beispiel fĂŒr ES 10 kann wie folgt umgeschrieben werden:


 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
 

Das Beispiel ist unnötig kompliziert, um private Eigenschaften, Methoden und Attribute gleichzeitig zu demonstrieren. Aber im Allgemeinen erfreut JS - das Auge mit seiner PrĂ€gnanz im Vergleich zur PHP-Version. Keine private Funktion _... fĂŒr Sie, keine Semikolons am Ende der Zeile und ein Punkt anstelle von "->", um tiefer in das Objekt einzudringen.


Benannte Getter. FĂŒr dynamische Namen Proxy-Objekte.


Es scheint Kleinigkeiten zu sein, aber nach dem Wechsel zu JS besteht immer weniger der Wunsch, zu PHP zurĂŒckzukehren.


Private Accessoren sind ĂŒbrigens nur mit Babel 7.3.0 und höher verfĂŒgbar.


Zum Zeitpunkt des Schreibens ist die neueste Version von npmjs.com 7.2.2


Ich freue mich auf Stufe 4!




Shebang Grammatik


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


Hashbang ist eine Methode, mit der Unix einen Interpreter fĂŒr eine ausfĂŒhrbare Datei angibt:


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

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

Chrome wirft SyntaxError: Invalid or&nbsp;unexpected token einen SyntaxError: Invalid or&nbsp;unexpected token auf eine Àhnliche SyntaxError: Invalid or&nbsp;unexpected token


Große Zahlen mit BigInt


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


Browser-UnterstĂŒtzung

BrowserunterstĂŒtzung fĂŒr BigInt () primitive


Die maximale Ganzzahl, die in JavaScript sicher verwendet werden kann (2⁔³ - 1):


 console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991 

BigInt wird benötigt, um Zahlen mit beliebiger Genauigkeit zu verwenden.


Dieser Typ wird auf verschiedene Arten deklariert:


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

Dies ist ein neuer primitiver Typ:


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

Es kann mit gewöhnlichen Zahlen verglichen werden:


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

Mathematische Operationen mĂŒssen jedoch innerhalb eines Typs ausgefĂŒhrt werden:


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

UnĂ€res Minus wird unterstĂŒtzt, unĂ€res Plus gibt einen Fehler zurĂŒck:


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


globalThis - eine neue Möglichkeit, auf den globalen Kontext zuzugreifen


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


arbeitet in Chrom


Da globale Bereichsimplementierungen von einer bestimmten Engine abhÀngen, mussten Sie zuvor Folgendes tun:


 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'); }; 

Und selbst diese Option garantierte nicht, dass alles sicher funktionieren wĂŒrde.


globalThis ist eine gemeinsame Methode fĂŒr alle Plattformen, um auf den globalen Bereich zuzugreifen:


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



Dynamischer import(dynamic)


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


Browser-UnterstĂŒtzung

BrowserunterstĂŒtzung fĂŒr dynamische Importe


Ich wollte Variablen in den Importzeilen Mit dynamischen Importen wurde dies möglich:


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

Der dynamische Import ist eine asynchrone Operation. Gibt ein Versprechen zurĂŒck, dass das Modul nach dem Laden an die RĂŒckruffunktion zurĂŒckgegeben wird.


Daher können Sie Module laden - bei Bedarf zurĂŒckgestellt:


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

Syntaktisch sieht dies wie ein Aufruf der Funktion import() aus, erbt jedoch nicht von Function.prototype , was bedeutet, dass es nicht gelingt, ĂŒber call oder apply :


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



import.meta - Metainformationen zum geladenen Modul.


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


arbeitet in Chrom


Im Code des geladenen Moduls wurde es möglich, Informationen darĂŒber zu erhalten. Dies ist nur die Adresse, unter der das Modul geladen wurde:


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



JSON.stringify() -Methode


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


GemĂ€ĂŸ Abschnitt 8.1 von RFC 8259 muss JSON- Text, der außerhalb eines geschlossenen Ökosystems ausgetauscht wird, mit UTF-8 codiert werden. JSON.stringify kann jedoch Zeichenfolgen zurĂŒckgeben, die Codepunkte enthalten, die in UTF-8 nicht dargestellt sind (insbesondere Ersatzcodepunkte) von U + D800 bis U + DFFF)


Die Zeile \uDF06\uD834 nach der Verarbeitung von JSON.stringify () wird also zu \\udf06\\ud834 :


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

Dies sollte nicht sein, und die neue Spezifikation behebt dies. Edge und Chrome wurden bereits aktualisiert.




Veraltete RegExp-Funktionen


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


Spezifikation fĂŒr Ă€ltere RegExp- Funktionen wie RegExp.$1 und RegExp.prototype.compile() .




Prototyp-String-Methoden .trimStart() und .trimEnd()


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


arbeitet in Chrom


.padStart() Analogie zu den Methoden .padStart() und .padEnd() das Leerzeichen am Anfang bzw. Ende der Zeile ab:


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



.matchAll () ist eine neue Prototyp-String-Methode.


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


arbeitet in Chrom


Funktioniert wie die .match() -Methode mit .match() g Flag, gibt jedoch einen Iterator zurĂŒck:


 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] 

Das Argument muss ein regulÀrer Ausdruck sein, andernfalls wird eine Ausnahme ausgelöst:


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







Zusammenfassung


Stufe 4 brachte weitere kosmetische VerÀnderungen. Das Interesse ist Stufe 3 . Die meisten VorschlÀge in Chrome sind bereits implementiert, und die Eigenschaften von Objekten freuen sich sehr darauf.






Korrekturen im Artikel



Wenn Sie eine Ungenauigkeit im Artikel, einen Fehler oder eine ErgĂ€nzung festgestellt haben, können Sie mir eine persönliche Nachricht schreiben. Es ist jedoch besser, das Artikel-Repository selbst zu verwenden: https://github.com/KasperGreen/es10 . FĂŒr den aktiven Beitrag werde ich mit KDPV eine gelbe Magnetmedaille vergeben.


Verwandte Materialien


Material in Englisch Aktuelle Version des Ecma-262-Standards


Material in Englisch Entwurf der nÀchsten Version des Ecma-262-Standards


ECMAScript


Neue # private Klassenfelder in JavaScript


Artikel ĂŒber HabrĂ© Übersicht ĂŒber die ES7-, ES8- und ES9-Standards


Shebang


Artikel ĂŒber HabrĂ© BigInt - lange Arithmetik in JavaScript


Artikel ĂŒber HabrĂ© JavaScript-Modulpfad


Material in Englisch Warum nicht privat x


Artikel ĂŒber HabrĂ© ECMAScript-Vorschlag: Array.prototype. {Flat, flatMap}


Öffentliche und private Klassenfelder


JavaScript: Das große Ganze gut warum




UPD (MĂ€rz):


Der Status wurde in Stufe 4 geÀndert:


‱ .trimStart() und .trimEnd() - Prototyp-String-Methoden # ;


‱ .matchAll() - .match() mit dem globalen Flag # ;


Alternativen KDPV mit gelbem Magneten von elfafeya.art
Foto von: kasper.green; Gelber Magnet: elfafeya.art & kasper.green

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


All Articles