JavaScript-Handbuch Teil 9: Übersicht über die ES7-, ES8- und ES9-Standards

Heute, im neunten Teil der Übersetzung des JavaScript-Handbuchs, wird ein Überblick über die Funktionen gegeben, die dank der Standards ES7, ES8 und ES9 in der Sprache erschienen sind.

Teil 1: Erstes Programm, Sprachfunktionen, Standards
Teil 2: Codestil und Programmstruktur
Teil 3: Variablen, Datentypen, Ausdrücke, Objekte
Teil 4: Funktionen
Teil 5: Arrays und Loops
Teil 6: Ausnahmen, Semikolons, Platzhalterliterale
Teil 7: Strict Mode, dieses Schlüsselwort, Ereignisse, Module, mathematische Berechnungen
Teil 8: Übersicht über die ES6-Funktionen
Teil 9: Übersicht über die ES7-, ES8- und ES9-Standards



ES7 Standard


Der ES7-Standard, der gemäß der offiziellen Terminologie ES2016 heißt, wurde im Sommer 2016 veröffentlicht. Er, im Vergleich zu ES6, in die Sprache gebracht, ist nicht viel neu. Insbesondere sprechen wir über Folgendes:

  • Array.prototype.includes() -Methode.
  • Potenzierungsoperator.

▍ Methode Array.prototype.includes ()


Die Methode Array.prototype.includes() dient zum Überprüfen des Vorhandenseins eines Elements im Array. Wenn Sie das gewünschte Element im Array finden, wird true , nicht - false . Vor ES7 wurde die Methode indexOf() verwendet, um dieselbe Operation auszuführen. Wenn ein Element gefunden wird, wird der erste Index zurückgegeben, anhand dessen es im Array gefunden werden kann. Wenn indexOf() das Element nicht findet, gibt es die Zahl -1 .

Gemäß den Konvertierungsregeln für JavaScript-Typen wird die Zahl -1 in true konvertiert. indexOf() die Ergebnisse der Operation von indexOf() zu überprüfen indexOf() sollte daher eine nicht besonders bequeme Konstruktion der folgenden Form verwendet werden.

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

Wenn in einer ähnlichen Situation unter der Annahme, dass indexOf() , ohne ein Element zu finden, false zurückgibt, etwas wie das unten gezeigte verwendet wird, funktioniert der Code nicht richtig.

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

In diesem Fall stellt sich heraus, dass die Konstruktion ![1,2].indexOf(3) false ergibt.

Mit der includes() -Methode sehen solche Vergleiche viel logischer aus.

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

In diesem Fall gibt die Konstruktion [1,2].includes(3) false , dieser Wert ist ein Operator ! wird auf true und die Konsole erhält eine Meldung, dass das Element im Array nicht gefunden wurde.

▍ Potenzierungsoperator


Der Exponentiationsoperator führt dieselbe Funktion wie die Math.pow() -Methode aus, ist jedoch bequemer als eine Bibliotheksfunktion, da sie Teil der Sprache ist.

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

Dieser Operator kann als angenehme Ergänzung zu JS angesehen werden, was in Anwendungen nützlich ist, die bestimmte Berechnungen durchführen. Ein ähnlicher Operator existiert in anderen Programmiersprachen.

ES8 Standard


Der ES8-Standard (ES2017) wurde 2017 veröffentlicht. Er brachte wie ES7 nicht viel in die Sprache. Wir sprechen nämlich über die folgenden Merkmale:

  • Hinzufügen von Zeichenfolgen zu einer bestimmten Länge.
  • Methode Object.values() .
  • Methode Object.entries() .
  • Methode Object.getOwnPropertyDescriptors() .
  • Nachgestellte Kommas in Funktionsparametern.
  • Asynchrone Funktionen.
  • Arbeiten Sie mit Shared Memory und atomaren Operationen.

▍ Hinzufügen von Zeilen zu einer bestimmten Länge


ES8 führte zwei neue String Objektmethoden ein - padStart() und padEnd() .

Die padStart() -Methode füllt die aktuelle Zeile mit einer weiteren Zeile, bis die letzte Zeile die gewünschte Länge erreicht hat. Das Befüllen erfolgt am Zeilenanfang (links). Hier erfahren Sie, wie Sie diese Methode verwenden.

 str.padStart(targetLength [, padString]) 

Hier ist str die aktuelle Zeile, targetLength die Länge der letzten Zeile (wenn sie kleiner als die Länge der aktuellen Zeile ist, wird diese Zeile ohne Änderungen zurückgegeben), padString ist ein optionaler Parameter - die Zeile, die zum Füllen der aktuellen Zeile verwendet wird. Wenn padString nicht angegeben ist, wird ein Leerzeichen verwendet, padString aktuelle Zeile auf die angegebene Länge padString .

Die padEnd() -Methode ähnelt padStart() , die Zeile wird jedoch rechts ausgefüllt.

Betrachten Sie Beispiele für die Verwendung dieser Methoden.

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

Hier wurden bei Verwendung von padStart() mit nur der gewünschten Länge der resultierenden Zeichenfolge Leerzeichen am Anfang der ursprünglichen Zeichenfolge hinzugefügt. Bei Verwendung von padEnd() mit der Länge der letzten Zeile und der zu füllenden Zeile wurden die Zeichen * am Ende der ursprünglichen Zeile hinzugefügt.

▍ Methode Object.values ​​()


Diese Methode gibt ein Array zurück, das die Werte der eigenen Eigenschaften des Objekts enthält, dh die Eigenschaften, die das Objekt selbst enthält, und nicht diejenigen, auf die es über die Prototypkette zugreifen kann.

Hier erfahren Sie, wie Sie es verwenden.

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

Diese Methode gilt auch für Arrays.

▍ Methode Object.entries ()


Diese Methode gibt ein Array zurück, von dem jedes Element auch ein Array ist, das im Format [key, value] Schlüssel und Werte der eigenen Eigenschaften des Objekts enthält.

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

Wenn Sie diese Methode auf Arrays anwenden, werden die Indizes der Elemente als Schlüssel angezeigt, und was im Array an den entsprechenden Indizes gespeichert ist, wird als Werte angezeigt.

▍ Methode getOwnPropertyDescriptors ()


Diese Methode gibt Informationen zu allen Eigenschaften des Objekts zurück. Attributmengen (Deskriptoren) sind Objekteigenschaften zugeordnet. Insbesondere sprechen wir über die folgenden Attribute:

  • value - Der Wert der Eigenschaft des Objekts.
  • writable - enthält true wenn die Eigenschaft geändert werden kann.
  • get - enthält eine Getter-Funktion, die der Eigenschaft zugeordnet ist, oder, falls keine solche Funktion vorhanden ist, undefined .
  • set - enthält die Setter-Funktion für die Eigenschaft oder undefined .
  • configurable - wenn es false - die Eigenschaft kann nicht gelöscht werden, ihre Attribute können außer dem Wert nicht geändert werden.
  • enumerable - Wenn true in dieser Eigenschaft enthalten ist, ist die aufzählbar.

Hier erfahren Sie, wie Sie diese Methode verwenden.

 Object.getOwnPropertyDescriptors(obj) 

Es nimmt ein Objekt, dessen Eigenschaftsinformationen Sie herausfinden müssen, und gibt ein Objekt zurück, das diese Informationen enthält.

 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 } } */ 

Warum wird diese Methode benötigt? Tatsache ist, dass Sie damit kleine Kopien von Objekten erstellen und diese kopieren können, zusätzlich zu anderen Eigenschaften, Gettern und Setzern. Dies konnte nicht mit der Object.assign() -Methode durchgeführt werden, die im ES6-Standard zum Kopieren von Objekten enthalten war.

Das folgende Beispiel enthält ein Objekt mit einem Setter, das mithilfe von console.log() anzeigt, was in die entsprechende Eigenschaft geschrieben werden soll.

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

Versuchen wir, dieses Objekt mit der Methode assign() zu kopieren.

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

Wie Sie sehen können, funktioniert dieser Ansatz nicht. Die name Eigenschaft, die der Setter im ursprünglichen Objekt war, wird jetzt als reguläre Eigenschaft dargestellt.

Jetzt kopieren wir das Objekt mit den Methoden Object.defineProperties() (es erschien in ES5.1) und Object.getOwnPropertyDescriptors() .

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

Hier bleibt der Setter in der Kopie des Objekts.

Es ist zu beachten, dass die für Object.assign() spezifischen Einschränkungen auch für die Object.create() -Methode charakteristisch sind, wenn sie zum Klonen von Objekten verwendet werden.

▍Vollendungskommas in Funktionsparametern


Mit dieser Funktion können Sie beim Deklarieren und beim Aufrufen von Funktionen ein Komma am Ende der Liste der Parameter bzw. Argumente lassen.

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

Dies verbessert die Benutzerfreundlichkeit von Versionskontrollsystemen. Wir sprechen nämlich von der Tatsache, dass Sie beim Hinzufügen neuer Parameter zu einer Funktion den vorhandenen Code nicht nur zum Einfügen eines Kommas ändern müssen.

▍Asynchrone Funktionen


Das Konstrukt async/await ist im ES2017-Standard enthalten, der als wichtigste Neuerung dieser Sprachversion angesehen werden kann.

Asynchrone Funktionen sind eine Kombination aus Versprechungen und Generatoren. Sie vereinfachen Konstruktionen, für deren Beschreibung zuvor eine große Menge an Vorlagencode und unbequeme Versprechungsketten erforderlich waren. In der Tat sprechen wir über eine Abstraktion auf hoher Ebene über Versprechen.

Als im ES2015-Standard Versprechungen auftauchten, wurden sie entwickelt, um bestehende Probleme mit asynchronem Code zu lösen, was sie auch taten. In den zwei Jahren, in denen die Standards ES2015 und ES2017 geteilt wurden, wurde jedoch klar, dass Versprechen nicht als endgültige Lösung für diese Probleme angesehen werden können.

Die Versprechen zielten insbesondere darauf ab, das Problem der „Rückrufhölle“ zu lösen, aber nachdem sie dieses Problem gelöst hatten, zeigten sie selbst aufgrund der Komplexität des Codes, in dem sie verwendet werden, nicht ihre beste Seite. Tatsächlich löst die asynchrone async/await Konstruktion das Problem der Versprechen und verbessert die Verwendbarkeit von asynchronem Code.

Betrachten Sie ein Beispiel.

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

Dieser Code gibt Folgendes an die Konsole aus.

 Before After I did something 

Wie Sie sehen, doSomething() Programm nach dem Aufruf von doSomething() weiter ausgeführt, nachdem Before , Nachher in der Konsole angezeigt wurde und nachdem drei Sekunden vergangen sind, habe I did something .

Serieller asynchroner Funktionsaufruf


Bei Bedarf können asynchrone Funktionen so etwas wie Aufrufketten bilden. Solche Designs zeichnen sich durch eine bessere Lesbarkeit aus als ähnliche, die ausschließlich auf Versprechungen beruhen. Dies ist im folgenden Beispiel zu sehen.

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

▍ Shared Memory und atomare Operationen


Hier geht es um das SharedArrayBuffer- Objekt, mit dem Sie gemeinsam genutzte Speicherbereiche beschreiben können, und das Atomics- Objekt, das eine Reihe von atomaren Operationen in Form statischer Methoden enthält. Details zu den Möglichkeiten, die diese Objekte dem Programmierer bieten, finden Sie hier .

ES9 Standard


ES9 (ES2018) ist die neueste Version des Standards zum Zeitpunkt der Veröffentlichung dieses Materials. Hier sind die Hauptmerkmale:

  • Wenden Sie Spread- und Rest-Anweisungen auf Objekte an.
  • Asynchrone Iteratoren.
  • Methode Promise.prototype.finally() .
  • Verbesserungen des regulären Ausdrucks.

▍Anwendung von Spread- und Rest-Operatoren auf Objekte


Wir haben bereits über die übrigen und verbreiteten Operatoren gesprochen, die in ES6 erschienen sind und für die Arbeit mit Arrays verwendet werden können. Beide sehen aus wie drei Punkte. Mit dem Rest-Operator im folgenden Beispiel für die Destrukturierung eines Arrays können Sie das erste und das zweite Element in die Konstanten first und second und den Rest in die Konstante others .

 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 ] 

Mit dem spread Operator können Sie Arrays an Funktionen übergeben, die regelmäßige Parameterlisten erwarten.

 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 

Mit demselben Ansatz können Sie jetzt mit Objekten arbeiten. Hier ist ein Beispiel für die Verwendung der rest-Anweisung in einer destruktiven Zuweisungsoperation.

 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 } 

Hier ist die Spread-Anweisung, die beim Erstellen eines neuen Objekts basierend auf einem vorhandenen Objekt verwendet wird. Dieses Beispiel setzt das vorherige fort.

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

▍Asynchrone Iteratoren


Mit dem neuen for-await-of Konstrukt können Sie asynchrone Funktionen aufrufen, die Versprechen in Schleifen zurückgeben. Solche Schleifen warten auf die Lösung des Versprechens, bevor sie mit dem nächsten Schritt fortfahren. So sieht es aus.

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

Gleichzeitig sollte beachtet werden, dass solche Schleifen in asynchronen Funktionen verwendet werden sollten - genauso wie bei der Arbeit mit dem Konstrukt async/await .

▍ Promise.prototype.finally () -Methode


Wenn das Versprechen erfolgreich gelöst wurde, wird die nächste then() -Methode aufgerufen. Wenn etwas schief geht, wird die catch() -Methode aufgerufen. Mit der Methode finally() können Sie Code ausführen, unabhängig davon, was zuvor passiert ist.

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

▍ Verbesserungen des regulären Ausdrucks


Reguläre Ausdrücke können Zeichenfolgen nachträglich überprüfen ( ?<= ). Auf diese Weise können Sie in den Zeilen nach bestimmten Konstruktionen suchen, vor denen sich einige andere Konstruktionen befinden.

Die Möglichkeit, Überprüfungen mit dem Konstrukt ?= Vorangehen zu können, war in regulären Ausdrücken vorhanden, die vor dem ES2018-Standard in JavaScript implementiert wurden. Solche Überprüfungen zeigen an, ob ein anderes Fragment einem bestimmten Fragment einer Zeile folgt.

 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 

Bau ?! führt die entgegengesetzte Operation aus - eine Übereinstimmung wird nur gefunden, wenn eine andere Zeile nicht der angegebenen Zeile folgt.

 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 

Bei der nachträglichen Überprüfung wird, wie bereits erwähnt, die Konstruktion ?<= Verwendet.

 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 

Die der beschriebenen entgegengesetzte Operation kann mit der Konstruktion ?<! .

 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 

Unicode-Regex-Escape-Sequenzen


In regulären Ausdrücken können Sie die Klasse \d , die einer beliebigen Ziffer entspricht, die Klasse \s , die einem beliebigen Leerzeichen entspricht, die Klasse \w , die einem beliebigen alphanumerischen Zeichen entspricht, usw. Die betreffende Funktion erweitert den Satz von Klassen, die in regulären Ausdrücken verwendet werden können, sodass Sie mit Unicode-Sequenzen arbeiten können. Wir sprechen über die Klasse \p{} und die Umkehrung der Klasse \P{} .

In Unicode verfügt jedes Zeichen über eine Reihe von Eigenschaften. Diese Eigenschaften sind in geschweiften Klammern der Gruppe \p{} . Beispielsweise bestimmt die Script Eigenschaft die Sprachfamilie, zu der ein Zeichen gehört. Die logische ASCII Eigenschaft true für ASCII-Zeichen usw. Wir werden beispielsweise herausfinden, ob einige Zeilen nur ASCII-Zeichen enthalten.

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

Die Eigenschaft ASCII_Hex_Digit true nur für Zeichen, die zum Schreiben von Hexadezimalzahlen verwendet werden können.

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

Es gibt viele andere ähnliche Eigenschaften, die auf die gleiche Weise wie oben beschrieben verwendet werden. Unter ihnen sind Uppercase , Lowercase , White_Space , Alphabetic , Emoji .

Im Script erfahren Sie beispielsweise, wie Sie mithilfe der Script Eigenschaft bestimmen, welches Alphabet in einer Zeichenfolge verwendet wird. Hier überprüfen wir die Zeichenfolge auf die Verwendung des griechischen Alphabets.

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

Details zu diesen Eigenschaften finden Sie hier .

Benannte Gruppen


Erfasste Zeichengruppen in ES2018 können mit Namen versehen werden. So sieht es aus.

 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' } ] */ 

Ohne die Verwendung benannter Gruppen wären dieselben Daten nur als Array-Elemente verfügbar.

 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 ] */ 

Regex-Flagge s


Die Verwendung des s Flags führt zu einem Zeichen . (Punkt) stimmt unter anderem mit dem Zeilenumbruchzeichen überein. Ohne dieses Flag entspricht ein Punkt einem beliebigen Zeichen mit Ausnahme einer neuen Zeile.

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

Zusammenfassung


Mit diesem Material schließen wir die Veröffentlichung der Übersetzungen dieses JavaScript-Handbuchs ab. Wir hoffen, dass diese Veröffentlichungen denjenigen, die zuvor noch nicht mit JavaScript gearbeitet hatten, geholfen haben, ihre ersten Schritte bei der Programmierung in dieser Sprache zu unternehmen.

Liebe Leser! Wenn Sie noch nie in JS geschrieben und diese Sprache in diesem Handbuch beherrschen, teilen Sie uns bitte Ihre Eindrücke mit.

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


All Articles