Einführung in ECMAScript 6 (ES-2015)

Einführung in ES6



Inhaltsverzeichnis
1. Vorlagenliterale
2. let und const
3. Pfeilfunktionsausdrücke
4. Für ... von
5. Berechnete Eigenschaftsnamen
6. Object.assign ()
7. Ruheparameter
8. Standardparameter
9. Destrukturierungsauftrag
10. Karte
11. Stellen Sie ein
12. Klassen
13. Versprechen
14. Iteratoren
15. Generatoren
16. Sumbol

Vorlagenliterale (Vorlagenzeichenfolgen)


Vorlagenliterale sind Zeichenfolgenliterale, die die Verwendung von Ausdrücken im Inneren ermöglichen. Mit ihnen können Sie mehrzeilige Literale und Zeichenfolgeninterpolation verwenden.

Vorlagenliterale sind in Backticks (``) anstelle von Double oder Single eingeschlossen. Sie können Platzhalter enthalten, die durch ein Dollarzeichen und geschweifte Klammern ($ {expression}) gekennzeichnet sind. Substitutionsausdrücke und der Text zwischen ihnen werden an die Funktion übergeben. Standardmäßig verkettet die Funktion einfach alle Teile zu einer Zeichenfolge. Wenn vor der Zeile ein Ausdruck steht (hier ist es ein Tag), wird die Vorlagenzeile als "Tag-Vorlage" bezeichnet. In diesem Fall wird der Tag-Ausdruck (normalerweise eine Funktion) mit dem verarbeiteten Vorlagenliteral aufgerufen, das Sie vor der Ausgabe ändern können. Geben Sie den Backslash \ an, um das Backquote in Vorlagenliteralen zu umgehen.

Mehrzeilige Literale
Zeilenumbruchzeichen sind Teil von Platzhalterliteralen. Bei Verwendung regulärer Zeichenfolgen würde das Einfügen von Wraps die folgende Syntax erfordern:
console.log('string text line 1\n' + 'string text line 2'); // "string text line 1 // string text line 2" 

Gleiches gilt für die Verwendung von Vorlagenliteralen:
 console.log(`string text line 1 string text line 2`); // "string text line 1 // string text line 2" 


Ausdrucksinterpolation
Um Ausdrücke in reguläre Zeichenfolgen einzufügen, müssten Sie die folgende Syntax verwenden:
 var a = 5; var b = 10; console.log('Fifteen is ' + (a + b) + ' and not ' + (2 * a + b) + '.'); // "Fifteen is 15 and not 20." 


Mit Hilfe von Vorlagenliteralen können Sie jetzt "syntaktischen Zucker" verwenden, wodurch solche Substitutionen besser lesbar werden:
 var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); // "Fifteen is 15 and not 20." 


Verschachtelte Vorlagen
Manchmal ist das Verschachteln eines Musters die kürzeste und vielleicht besser lesbare Möglichkeit, eine Zeichenfolge zu erstellen. Fügen Sie einfach eine weitere in die hinter zitierte Vorlage ein und verpacken Sie sie in die $ {} -Ersetzung. Wenn der Ausdruck beispielsweise true ist, können Sie ein Vorlagenliteral zurückgeben.
In ES5:
 var classes = 'header' classes += (isLargeScreen() ? '' : item.isCollapsed ? ' icon-expander' : ' icon-collapser'); 

In ES2015 mit Vorlagenliteralen ohne Verschachtelung:
 const classes = `header ${ isLargeScreen() ? '' : (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`; 

In ES2015 mit verschachtelten Vorlagenliteralen:
 const classes = `header ${ isLargeScreen() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`; 


Tag-Vorlagen
Eine erweiterte Form von Vorlagenliteralen wird mit Vorlagen versehen. Mit ihnen können Sie Vorlagenliterale mithilfe einer Funktion analysieren. Das erste Argument einer solchen Funktion enthält ein Array von Zeichenfolgenwerten, und der Rest enthält Ausdrücke aus Substitutionen. Infolgedessen sollte die Funktion die zusammengesetzte Zeichenfolge zurückgeben (oder etwas völlig anderes, wie später gezeigt wird). Der Name der Funktion kann beliebig sein.
 var person = 'Mike'; var age = 28; function myTag(strings, personExp, ageExp) { var str0 = strings[0]; // "That " var str1 = strings[1]; // " is a " // ,     // (  )    , //    (""),    . // var str2 = strings[2]; var ageStr; if (ageExp > 99){ ageStr = 'centenarian'; } else { ageStr = 'youngster'; } //     ,     return `${str0}${personExp}${str1}${ageStr}`; } var output = myTag`That ${ person } is a ${ age }`; console.log(output);// That Mike is a youngster 

Die Tag-Funktion ist nicht erforderlich, um eine Zeichenfolge zurückzugeben.

Rohe Linien
Mit der speziellen Raw-Eigenschaft, die für das erste Argument der Tag-Vorlage verfügbar ist, können Sie die Zeichenfolge ohne Interpretation in der Form abrufen, in der sie eingegeben wurde.
 function tag(strings) { return strings.raw[0]; } tag`string text line 1 \\n string text line 2`; //  "string text line 1 \\n string text line 2", //  'n'    '\' 

Darüber hinaus gibt es eine String.raw () -Methode, die genau dieselbe Quellzeichenfolge zurückgibt, die die Standardvorlagenfunktion und die Zeichenfolgenverkettung zusammen zurückgeben würden.

In ECMAScript 2016 folgen getaggte Vorlagen den Regeln für das Escapezeichen der folgenden Zeichen:
  • Unicode-Zeichen, die mit "\ u" beginnen, z. B. \ u00A9
  • Unicode-Codepunkte, die mit "\ u {}" beginnen, z. B. \ u {2F804}
  • hexadezimale Zeichendarstellungen, die mit "\ x" beginnen, z. B. \ xA9
  • Oktale Darstellungen von Zeichen, die mit "\" beginnen, z. B. \ 251


let und const


Der Umfang der Variablen, die durch die Schlüsselwörter let und const deklariert werden, ist der Block, in dem sie deklariert werden, und alles unter den Blöcken. In diesem Fall ähnelt die Funktionsweise der let-Direktive der der var-Direktive. Der Hauptunterschied besteht darin, dass der Umfang der von der var-Direktive deklarierten Variablen die gesamte Funktion ist, in der sie deklariert ist. Zusätzlich zu Variablen kann der Wert von Konstanten weder durch eine neue Zuweisung geändert noch neu definiert werden. Wenn Sie eine Variable mit dem Schlüsselwort const deklarieren, müssen Sie den Zuweisungsoperator verwenden, um den Wert der Konstante festzulegen.

Globale Konstanten werden im Gegensatz zu var-Variablen nicht zu Eigenschaften des Fensterobjekts.
Die Initialisierung einer Konstante ist erforderlich.
Sie müssen gleichzeitig mit der Deklaration einen Wert angeben (der Punkt ist, dass dieser Wert dann nicht mehr geändert werden kann).
Durch das Deklarieren von Variablen mit dem Schlüsselwort const wird eine Konstante (eine neue benannte Referenz auf einen Speicherbereich) erstellt, die schreibgeschützt ist.
Dies bedeutet nicht, dass der angegebene Wert unverändert bleibt, aber es bedeutet, dass der Bezeichner nicht neu zugewiesen werden kann. Wenn beispielsweise eine Konstante auf ein Objekt zeigt, kann das Objekt selbst geändert werden.
Namen von Konstanten dürfen nicht mit Namen von Funktionen oder Variablen desselben Bereichs übereinstimmen.

Ein Beispiel für den Unterschied zwischen globalem und Blockbereich:
 function myFunction() { if (true) let a = 5; console.log(a); //SyntaxError   a     if if (true) var b = 5; console.log(b); //5   b     } 


Pfeilfunktionsausdrücke


Pfeilfunktionsausdrücke haben eine kürzere Syntax als funktionale Ausdrücke und sind lexikalisch an den Wert von this gebunden (aber nicht an ihre eigenen Argumente, super oder new.target). Der Ausdruck von Pfeilfunktionen ermöglicht es Ihnen nicht, einen Namen anzugeben. Daher sind Pfeilfunktionen anonym, sofern sie nichts zugewiesen sind.

Grundlegende Syntax
 (param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression // : (param1, param2, …, paramN) => { return expression; } //       : (singleParam) => { statements } singleParam => { statements } //       : () => { statements } () => expression // : () => { return expression; } 


Erweiterte Syntax
 //     ,     params => ({foo: bar}) // Rest       (param1, param2, ...rest) => { statements } (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } //    var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6 

Weitere Informationen zu Pfeilfunktionen finden Sie hier .

Für ... von


Die for ... of-Anweisung führt eine Schleife durch iterierbare Objekte (einschließlich Array, Map, Set, ein Objekt mit Argumenten und dergleichen) aus und ruft bei jedem Iterationsschritt die Operatoren für jeden Wert aus verschiedenen Eigenschaften des Objekts auf.

Warum sollte eine for ... in-Schleife NICHT zum Iterieren verwendet werden? Denn je nach Engine kann JavaScript in zufälliger Reihenfolge iterieren, was zu unvorhersehbaren Ergebnissen führen kann. Wenn sich eine Eigenschaft in einer Iteration ändert und sich dann erneut ändert, ist ihr Wert in der Schleife der letzte Wert. Eine Eigenschaft, die vor Erreichen des Zyklus gelöscht wurde, nimmt nicht daran teil. Eigenschaften, die Objekten in der Schleife hinzugefügt wurden, können übersprungen werden. Im Allgemeinen ist es am besten, während der Iteration keine Eigenschaft zum Objekt hinzuzufügen, zu ändern oder zu löschen, wenn Sie sie noch nicht übergeben haben. Es gibt keine Garantie dafür, dass die hinzugefügte Eigenschaft vom Zyklus besucht, nach den Änderungen geändert und nach dem Löschen gelöscht wird. Darüber hinaus ist die iterative Variable eine Zeichenfolge und keine Zahl. Wenn Sie also Berechnungen mit der Variablen durchführen möchten, müssen Sie die Zeichenfolgen verketten, anstatt sie hinzuzufügen. Um logische Fehler zu vermeiden, sollten Sie es nicht verwenden!

Im Gegensatz zur for ... of-Schleife gibt die for ... in-Schleife alle aufgezählten Eigenschaften zurück, einschließlich derjenigen mit nicht ganzzahligen und geerbten Namen.

Für ... der Schleifensyntax
 for (var i of arr) //for ( of ) arr[i] = "something value" 

Beispiele:
 Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; iterable.foo = 'hello'; for (let i in iterable) console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom" for (let i in iterable) { if (iterable.hasOwnProperty(i)) console.log(i); //  0, 1, 2, "foo" } for (let i of iterable) console.log(i); // 3, 5, 7 

Jedes Objekt erbt die objCustom-Methode und jedes Array erbt die arrCustom-Methode, indem es sie in Object.prototype und Array.prototype erstellt. Das iterierbare Objekt erbt die Methoden objCustom und arrCustom aufgrund der Vererbung von Prototypen.

Die Schleife zeigt nur die aufgezählten Eigenschaften des iterierbaren Objekts in der Reihenfolge an, in der sie erstellt wurden. Die Werte 3, 5, 7 und Hallo werden nicht gedruckt, da sie nicht aufzählbar sind. Die Namen von Eigenschaften und Methoden werden angezeigt, z. B. arrCustom und objCustom.

Die Schleife ähnelt der vorherigen, verwendet jedoch hasOwnProperty (), um zu überprüfen, ob diese Eigenschaft des Objekts eine eigene oder eine geerbte ist. Es werden nur eigene Eigenschaften angezeigt. Die Namen 0, 1, 2 und foo gehören nur zur Instanz des Objekts (nicht vererbt). Die Methoden arrCustom und objCustom werden nicht ausgegeben, da sie vererbt werden.

Diese Schleife umgeht iterierbar und zeigt die Werte des iterierbaren Objekts an, die in der Methode des Iterierens definiert sind, d. H. nicht die Eigenschaften des Objekts, sondern die Werte des Arrays 3, 5, 7.

Berechnete Eigenschaftsnamen


Die Syntax zum Deklarieren von Objekten und ihren Elementen unterstützt berechnete Eigenschaftsnamen. Auf diese Weise können Sie den Klammern [] einen Ausdruck hinzufügen, der als Name der Eigenschaft ausgewertet wird. Es ähnelt Vorlagenliteralen.

Beispiel für berechnete Namen:
 var a = () => "world"; var a = { ["a" + (10 - 6)]: { ["some" + "string"]: true, [10 + 20]: 10, [`hello ${a()}`]: a() } } 



Object.assign ()


Die Object.assign () -Methode wird verwendet, um die Werte aller eigenen aufgezählten Eigenschaften von einem oder mehreren Quellobjekten in das Zielobjekt zu kopieren. Nach dem Kopieren wird das Zielobjekt zurückgegeben.

Die Object.assign () -Methode kopiert nur aufgezählte und native Eigenschaften von den Quellobjekten in das Zielobjekt. Es verwendet die interne [[Get]] - Methode für die Quellobjekte und die interne [[Set]] - Methode für das Zielobjekt, ruft also auch Getter und Setter auf. Aus diesem Grund werden Eigenschaften zugewiesen, anstatt einfach neue Eigenschaften zu kopieren oder zu definieren. Dieses Verhalten kann dazu führen, dass die Methode nicht zum Einfügen neuer Eigenschaften in den Prototyp geeignet ist, wenn die eingefügten Quellobjekte Getter enthalten. Stattdessen sollten die Methoden Object.getOwnPropertyDescriptor () und Object.defineProperty () verwendet werden, um Prototypen von Eigenschaftsdefinitionen einschließlich eines Zeichens ihrer Aufzählung zu kopieren.

Die Eigenschaften der Typen von String und Symbol werden kopiert.

Im Fehlerfall, wenn die Eigenschaft beispielsweise nicht beschreibbar ist, wird eine TypeError-Ausnahme ausgelöst und das Zielobjekt bleibt unverändert.

Beachten Sie, dass die Object.assign () -Methode keine Ausnahme auslöst, wenn die Anfangswerte null oder undefiniert sind.

Beispiel: Klonen eines Objekts
 var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } 

Beispiel: Objekte zusammenführen
 var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 },     . 


Ruheparameter


Die Syntax der verbleibenden Parameter der Funktion ermöglicht es Ihnen, eine unbegrenzte Anzahl von Argumenten in Form eines Arrays darzustellen.

Wenn das zuletzt genannte Funktionsargument ein Präfix ... hat, wird es automatisch zu einem Array mit Elementen von 0 bis theArgs.length entsprechend der tatsächlichen Anzahl der an die Funktion übergebenen Argumente.

Syntax
 function(a, b, ...theArgs) { // ... } 


Ein Beispiel für die Verwendung der Syntax der verbleibenden Parameter:
 function name (a, b, ...c) {} name (0, 1, 2, 3,) 

In diesem Beispiel ist a = 0 b = 1 c [0] = 2 c [1] = 3
Wenn der verbleibende Parameter nicht übergeben wird, handelt es sich um ein leeres Array (im Gegensatz zu normalen Parametern ist es niemals undefiniert).

Diese Syntax kann nicht nur in Funktionsargumenten verwendet werden, sondern auch an anderen Stellen, beispielsweise zum Kopieren und Kombinieren von Arrays:

 var a = [ 0, 1, 2 ]; var b = [ 3, 4, 5 ]; var c = [ ...a, ...b ]; // [ 0, 1, 2, 3, 4, 5 ] 


Standardparameter


Mit Standardparametern können Sie formale Funktionsparameter auf Standardwerte setzen, wenn die Funktion ohne Argumente aufgerufen wird oder wenn der Parameter explizit undefiniert übergeben wird.

In JavaScript nehmen die Parameter einer Funktion, deren Werte beim Aufruf nicht übergeben werden, den undefinierten Standardwert an. In einigen Fällen kann es jedoch nützlich sein, einen anderen Standardwert festzulegen. In solchen Fällen sind die Standardeinstellungen vorgesehen.

Der Standardwert wird einem formalen Parameter nur zugewiesen, wenn während eines Funktionsaufrufs der Wert für diesen Parameter nicht oder undefiniert explizit übergeben wurde.

Ein Beispiel für die Verwendung von Standardparametern:
 function myFun(a=5) { return a*a; } console.log(myFun()); // 25 


Zerstörungsauftrag


Mit der Destrukturierungszuweisungssyntax in JavaScript-Ausdrücken können Sie Daten aus Arrays oder Objekten mithilfe einer Syntax abrufen, die der Deklaration eines Arrays oder von Literalen in einem Objekt ähnelt.

Objekt- oder Arraydeklarationsausdrücke bieten eine einfache Möglichkeit, ein homogenes Datenpaket zu erstellen. Wenn Sie ein solches Paket erstellen, haben Sie die Möglichkeit, es auf jede mögliche Weise zu verwenden. Sie können es auch in Funktionen zurückgeben.

Eine der wichtigsten Möglichkeiten zur Verwendung der destruktiven Zuweisung besteht darin, die Datenstruktur mit einem Operator zu lesen, obwohl Sie neben dieser Funktion noch viele andere Verwendungsmöglichkeiten finden können.

Beispiel für eine destruktive Zuordnung:
 var a, b, rest; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2 [a, b, ...rest] = [1, 2, 3, 4, 5]; console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5] ({a, b} = {a:1, b:2}); console.log(a); // 1 console.log(b); // 2 

Weitere Beispiele finden Sie hier .

Karte


Map - Ein Objekt, das Schlüssel-Wert-Paare enthält und die Einfügereihenfolge beibehält. Jeder Wert (sowohl Objekte als auch Grundelemente) kann als Schlüssel verwendet werden.

Ein Beispiel:
 var myMap = new Map(); var keyObj = {}, keyFunc = function () {}, keyString = "a string"; //   myMap.set(keyString, "value associated with 'a string'"); myMap.set(keyObj, "value associated with keyObj"); myMap.set(keyFunc, "value associated with keyFunc"); myMap.size; // 3 //   myMap.get(keyString); // "value associated with 'a string'" myMap.get(keyObj); // "value associated with keyObj" myMap.get(keyFunc); // "value associated with keyFunc" myMap.get("a string"); // "value associated with 'a string'" //   keyString === 'a string' myMap.get({}); // undefined,   keyObj !== {} myMap.get(function() {}) // undefined,   keyFunc !== function () {} 

Unterschied der Karte vom Objekt:

  • Objektschlüssel sind Linien und Symbole, während jeder Wert ein Kartenschlüssel sein kann, einschließlich Funktionen, Objekten und Grundelementen.
  • Im Gegensatz zu Objekten sind die Schlüssel in Map geordnet. Während der Map-Iteration werden die Schlüssel daher in der Einfügereihenfolge zurückgegeben.
  • Sie können die Anzahl der Elemente in einer Karte mithilfe der size-Eigenschaft leicht ermitteln, während die Anzahl der Elemente in einem Objekt nur manuell bestimmt werden kann.
  • Map ist ein iterierbares Objekt und kann direkt iteriert werden, während das Objekt den manuellen Empfang der Liste der Schlüssel und ihrer Iteration erfordert.
  • Das Objekt hat einen Prototyp und daher einen Standardschlüsselsatz, der sich bei Unachtsamkeit mit Ihren Schlüsseln überschneiden kann. Seit der Veröffentlichung von ES5 kann dies mit map = Object.create (null) geändert werden.
  • Map kann bei häufigem Hinzufügen oder Entfernen von Schlüsseln eine bessere Leistung erzielen.

Eigenschaften und Methoden:

  • Map.prototype.size - Gibt die Anzahl der Schlüssel / Wert-Paare auf einer Karte zurück
  • Map.prototype.set (Schlüssel, Wert) - Fügt Map das übergebene Schlüssel / Wert-Paar hinzu. Wenn der angegebene Schlüssel bereits vorhanden ist, wird er mit dem neuen Wert überschrieben.
  • Map.prototype.get (Schlüssel) - Gibt den Wert des übergebenen Schlüssels zurück. Wenn kein Schlüssel vorhanden ist, wird undefined zurückgegeben
  • Map.prototype.has (Schlüssel) - Gibt true zurück, wenn der übergebene Schlüssel vorhanden ist, und false, wenn dies nicht der Fall ist
  • Map.prototype.delete (Schlüssel) - Löscht das angegebene Schlüssel-Wert-Paar und gibt true zurück. Gibt false zurück, wenn der Schlüssel nicht vorhanden ist.
  • Map.prototype.clear () - Entfernt alle Schlüssel / Wert-Paare aus Map
  • Map.prototype.keys () - Gibt für jedes Element einen Iterator von Schlüsseln auf einer Map zurück
  • Map.prototype.values ​​() - Gibt für jedes Element einen Iterator von Werten auf der Map zurück
  • Map.prototype.entries () - Gibt für jedes Element einen Iterator des Arrays [Schlüssel, Wert] auf Map zurück


Stellen Sie ein


Ermöglicht das Speichern eindeutiger Werte eines beliebigen Typs, sowohl von Grundelementen als auch von anderen Objekttypen.

Festgelegte Objekte stellen Sammlungen von Werten dar, die Sie in der Reihenfolge durchlaufen können, in der die Elemente eingefügt werden. Der Wert eines Elements in Set kann nur in einer Instanz vorhanden sein, wodurch seine Eindeutigkeit in der Set-Auflistung sichergestellt wird.

Eigenschaften und Instanzmethoden festgelegt
  • size - Gibt die Anzahl der Elemente im Set-Objekt zurück.
  • add (Wert) - Fügt dem Set-Objekt ein neues Element mit dem angegebenen Wert hinzu. Gibt ein Set-Objekt zurück.
  • clear () - Entfernt alle Elemente aus dem Set-Objekt.
  • delete (value) - Löscht das dem Wert zugeordnete Element und gibt den Wert zurück, der (value) zuvor zurückgegeben hat. has (value) gibt später false zurück.
  • entry () - Gibt ein neues Iterator-Objekt zurück, das ein Array von [Wert, Wert] für jedes Element im Set-Objekt in Einfügereihenfolge enthält. Dies wird ähnlich wie das Map-Objekt gespeichert, sodass jeder Eintrag hier den gleichen Wert für seinen Schlüssel und Wert hat.
  • forEach (callbackFn [, thisArg]) - Ruft callbackFn einmal für jeden im Set-Objekt vorhandenen Wert in Einfügereihenfolge auf. Wenn thisArg für thisEach angegeben ist, wird es für diesen Rückruf als this-Wert verwendet.
  • has (Wert) - Gibt einen booleschen Wert zurück, der bestätigt, ob das Element mit dem angegebenen Wert im Set-Objekt vorhanden ist oder nicht.
  • values ​​() - Gibt ein neues Iterator-Objekt zurück, das die Werte für jedes Element im Set-Objekt in Einfügereihenfolge enthält.

Verwenden des Set-Objekts
 var mySet = new Set(); mySet.add(1); // Set { 1 } mySet.add(5); // Set { 1, 5 } mySet.add(5); // Set { 1, 5 } mySet.add("some text"); // Set { 1, 5, 'some text' } var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); //  o    ,      mySet.has(1); // true mySet.has(3); // false, 3     set mySet.has(5); // true mySet.has(Math.sqrt(25)); // true mySet.has("Some Text".toLowerCase()); // true mySet.has(o); // true mySet.size; // 5 mySet.delete(5); //  5  set mySet.has(5); // false, 5   mySet.size; // 4,     console.log(mySet); // Set {1, 'some text', Object {a: 1, b: 2}, Object {a: 1, b: 2}} 

Bypass-Set
 //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet.keys()) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} for (let item of mySet.values()) console.log(item); //    : 1, "some text", {"a": 1, "b": 2} //(key  value    ) for (let [key, value] of mySet.entries()) console.log(key); //  Set  Array var myArr = Array.from(mySet); // [1, "some text", {"a": 1, "b": 2}] //       HTML  mySet.add(document.body); mySet.has(document.querySelector("body")); // true //   Array  Set   mySet2 = new Set([1,2,3,4]); mySet2.size; // 4 [...mySet2]; // [1,2,3,4] //      var intersection = new Set([...set1].filter(x => set2.has(x))); //      var difference = new Set([...set1].filter(x => !set2.has(x))); //   set   forEach mySet.forEach(function(value) { console.log(value); }); // 1 // 2 // 3 // 4 



Klassen


Klassen in JavaScript wurden in ECMAScript 2015 eingeführt und sind syntaktischer Zucker über die Vererbung von Prototypen in JavaScript. Die Klassensyntax führt kein neues objektorientiertes Modell ein, bietet jedoch eine einfachere und intuitivere Möglichkeit, Objekte zu erstellen und die Vererbung zu organisieren.

Klassen sind eigentlich „Sonderfunktionen“. So wie Sie Funktionen (Funktionsausdrücke und Funktionsdeklarationen) definieren, können Sie Klassen definieren mit: Klassendeklarationen und Klassenausdrücken.

Der Unterschied zwischen einer Funktionsdeklaration und einer Klassendeklaration besteht darin, dass eine Funktionsdeklaration angehoben wird, eine Klassendeklaration jedoch nicht. Daher müssen Sie zuerst Ihre Klasse deklarieren und erst dann damit arbeiten, da sonst eine Ausnahme vom Typ ReferenceError ausgelöst wird.

Klassenerklärung


Die erste Möglichkeit, eine Klasse zu definieren, besteht in einer Klassendeklaration. Verwenden Sie dazu das Schlüsselwort class und geben Sie den Klassennamen an (im Beispiel „myClass“).
 class myClass{ constructor(height, width) { this.height = height; this.width = width; } } 

Die zweite Möglichkeit, eine Klasse zu definieren, ist der Klassenausdruck. Sie können benannte und namenlose Ausdrücke erstellen. Im ersten Fall befindet sich der Name des Klassenausdrucks im lokalen Bereich der Klasse und kann über die Eigenschaften der Klasse selbst und nicht über ihre Instanz abgerufen werden.
 //  var myClass = class { constructor(height, width) { this.height = height; this.width = width; } }; //  var myClass = class myClass { constructor(height, width) { this.height = height; this.width = width; } }; 

Klassenausdrücke unterliegen denselben Hebeproblemen wie Klassendeklarationen!

Klassendeklarationskörper und Klassenausdrücke werden im strengen Modus ausgeführt.
Der strikte Modus ändert die Syntax und das Verhalten der Laufzeit.
Genauer gesagt ist der strenge Modus durch Folgendes gekennzeichnet:
  • Konvertieren Sie Fehler in Ausnahmen
  • Änderungen, die die Berechnung einer Variablen in bestimmten Fällen der Verwendung ihres Namens vereinfachen;
  • , eval arguments;
  • , «» JavaScript;


  1. .
  2. .
  3. , , .
  4. ( ).
  5. , , . , .
  6. . .
  7. Die Syntax des Oktalzahlensystems ist verboten.
  8. Das Festlegen von Eigenschaften mit primitiven Werten ist verboten.

Vereinfachung der Arbeit mit Variablen Der
strenge Modus vereinfacht den Vergleich des Namens einer Variablen mit dem Ort ihrer Definition im Code.
  1. Die Verwendung mit ist verboten. Das Problem bei ist, dass zur Laufzeit jeder Name innerhalb des Blocks entweder auf eine Eigenschaft des zu verarbeitenden Objekts oder auf eine Variable im umgebenden (oder sogar globalen) Kontext verweisen kann - es ist unmöglich, dies vorher zu wissen. Eine einfache Alternative mit besteht bereits darin, das Objekt einer Variablen mit einem Kurznamen zuzuweisen und dann auf die gewünschte Eigenschaft als Eigenschaft dieser Variablen zuzugreifen.
  2. eval () im strengen Modus fügt dem umgebenden Kontext keine neuen Variablen hinzu.
  3. Es ist verboten, einfache Namen zu löschen.

Vereinfachung von Auswertung und Argumenten Der
strikte Modus reduziert die Anzahl der Kuriositäten im Verhalten von Argumenten und Auswertung, die beide eine gewisse Menge Magie in regulären Code mischen. Eval fügt also Variablen hinzu oder entfernt sie und ändert ihre Werte. Die Argumentvariable kann Sie mit ihren indizierten Eigenschaften überraschen, die Referenzen (Synonyme) für benannte Funktionsargumente sind.
  1. Die Schlüsselwörter eval und Argumente können nicht überschrieben oder geändert werden.
  2. Die Felder des Argumentobjekts sind nicht den benannten Funktionsargumenten zugeordnet, sondern sind ihre duplizierten Kopien der Werte.
  3. Die Eigenschaft rules.callee wird nicht unterstützt. Im regulären Code bezieht sich die Eigenschaft rules.callee auf die Funktion selbst, für deren Aufruf das Argumentobjekt erstellt wurde.

"Sicheres" JavaScript
Einige Websites bieten Benutzern die Möglichkeit, JavaScript zu schreiben, das auf der Website im Auftrag anderer Benutzer ausgeführt wird. In Browsern hat JavaScript möglicherweise Zugriff auf private Informationen, was eine Sicherheitslücke in JavaScript darstellt.
  1. Der an die Funktion übergebene Wert wird im strengen Modus nicht in das Objekt umgewandelt.
  2. Es ist nicht möglich, den JavaScript-Stack über die grundlegenden ECMAScript-Erweiterungen auszuführen.
  3. In Funktionen bietet die Eigenschaft rules keinen Zugriff mehr auf Variablen, die innerhalb der Funktion erstellt wurden.

Weitere Informationen zum Strict-Modus finden Sie in der ECMAScript 5.1- Spezifikation .
Und auch Dokumentation von Mozilla.

Konstruktoren


Der Konstruktor ist eine spezielle Methode zum Erstellen und Initialisieren von Objekten, die mit der Klasse erstellt wurden.
 class Student { constructor(name) { this.name = name; } } var robert = new Student('Robert'); console.log(robert.name); // Outputs 'Robert' 

Beim Erstellen neuer Objekte aus der Klasse wird Konstruktor () gestartet, der zum Initialisieren der Objekte erforderlich ist.

In einer Klasse namens Konstruktor kann es nur eine Methode geben. Wenn die Klasse mehr als einen Konstruktor enthält, wird eine SyntaxError-Ausnahme ausgelöst.

Das Schlüsselwort super kann im Konstruktor verwendet werden, um den Konstruktor der übergeordneten Klasse aufzurufen.

Wenn Sie keine Konstruktormethode definiert haben, wird der Standardkonstruktor verwendet.
Für Basisklassen lautet der Standardkonstruktor:
 constructor() {} 

Für abgeleitete Klassen lautet der Standardkonstruktor:
 constructor(...args) { super(...args); } 


Methoden


Syntax der Methodendeklaration:
 var obj = { property([parameters]) {}, get property() {}, set property(value) {}, * generator() {} }; 

Abkürzung für Generatormethoden
 var obj = { * g() { var index = 0; while(true) yield index++; } }; var it = obj.g(); console.log(it.next().value); // 0 console.log(it.next().value); // 1 


Alle Methodendefinitionen außer Generatormethoden können keine Konstruktoren sein und lösen einen TypeError aus, wenn Sie versuchen, sie zu instanziieren.

Berechnete Eigenschaftsnamen
 var obj = { ["foo" + 2](){ return 2; } console.log(obj.foo2()); // 2 }; 


Das Schlüsselwort static definiert statische Methoden für eine Klasse. Statische Methoden werden aufgerufen, ohne ihre Klasse zu instanziieren, und können nicht für Instanzen der Klasse aufgerufen werden.

Syntax von Gettern und Setzern
 class Student { constructor(name) { this.name = name; } get Name() { return this.name; } set Name(newName) { if(typeof(newName) != "string") throw new Error("Name is not a string!"); else this.name = newName; // Robert } } var robert = new Student('robert'); robert.Name = "Robert"; console.log(robert.Name); 

  • Setter - Erforderlich für die Validierung geschriebener Parameter (wie im obigen Beispiel)
  • getter - Wird benötigt, um Eigenschaften zu erhalten (obwohl sie direkt erhalten werden können). Kann keine Argumente haben

In ES6 ist keine Kapselung integriert, Sie können sie jedoch selbst organisieren. Zum Beispiel so:

 var Student = (function () { let privateProps = new WeakMap(); class Person { constructor(name, Age) { this.name = name; // public privateProps.set(this, {age: Age}); // private } get Age() { return privateProps.get(this).age; } set Age (newAge) { privateProps.set(this, {age: newAge}); } } return Person; })(); var robert = new Student('Robert', 19); robert.Age = 20; console.log(robert.Age); // 20 


Vererbung


Das Schlüsselwort extens wird in Klassendeklarationen und Klassenausdrücken verwendet, um eine Klasse zu erstellen, die ein untergeordnetes Element einer anderen Klasse ist.

 class Person { constructor (age) { this.age = age; } sayAge () { return this.age; } } class Student extends Person { constructor (name, age) { super(age); this.name = name; } sayFull () { return `Hello my name is ${this.name} and I'm ${super.sayAge()} years old`; } } var robert = new Student("Robert", 19); console.log(robert.sayFull()); // Hello my name is Robert and I'm 19 years old 


Im Konstruktor wird das Schlüsselwort super () als Funktion verwendet, die den übergeordneten Konstruktor aufruft. Es muss vor dem ersten Aufruf des Schlüsselworts this im Hauptteil des Konstruktors aufgerufen werden. Das Schlüsselwort super kann auch zum Aufrufen von Funktionen des übergeordneten Objekts verwendet werden.

Wenn Sie die Methoden der übergeordneten Klasse in der untergeordneten Klasse überschreiben, werden die Methoden der untergeordneten Klasse standardmäßig aufgerufen. Sie können die Methoden der übergeordneten Klasse jedoch explizit mit der Funktion super () aufrufen.
 class obj { constructor(name){ this.name = name; } displayName(){ return this.name.length; } } undefined class obj_2 extends obj { constructor(name) { super(name); } displayName() { //     return [this.name, super.displayName()]; } } var Obj = new obj_2("obj_2"); console.log(Obj.displayName()); // Array [ "obj_2", 5 ] 


Erweitern von Inline-Objekten mit Erweitern In
diesem Beispiel wird ein Inline-Datumsobjekt erweitert.
 class myDate extends Date { constructor() { super(); } getFormattedDate() { var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; return this.getDate() + '-' + months[this.getMonth()] + '-' + this.getFullYear(); } } 


Versprich es mir


Das Promise-Objekt wird für verzögerte und asynchrone Berechnungen verwendet.

Versprechen kann in drei Staaten sein:
  • ausstehend: Ausgangszustand, nicht abgeschlossen und nicht abgelehnt.
  • (fulfilled): .
  • (rejected): .

(pending), (fulfilled), (), (rejected), . , then. ( , , .. « », , , DOM.)

Promise.prototype.then() Promise.prototype.catch() , , .
Bild

(promise)
Ein Promise-Objekt wird mit dem neuen Schlüsselwort und seinem Konstruktor erstellt. Der Promise-Konstruktor verwendet ein Argument, das als Executor-Funktion bezeichnet wird, als Argument. Diese Funktion sollte zwei Rückruffunktionen als Parameter akzeptieren. Die erste (Auflösung) wird aufgerufen, wenn die asynchrone Operation erfolgreich abgeschlossen wurde und das Ergebnis ihrer Ausführung als Wert zurückgegeben hat. Der zweite Rückruf (Zurückweisen) wird aufgerufen, wenn die Operation fehlgeschlagen ist, und gibt einen Wert zurück, der den Grund für den Fehler angibt, meistens ein Fehlerobjekt.
 const myPromise = new Promise((resolve, reject) => { //   ,    : resolve(someValue); //   //  reject("failure reason"); //  }); 

Ein Funktionsobjekt mit zwei Argumenten, Auflösen und Ablehnen, bewirkt , dass das Versprechen erfolgreich ist, das zweite lehnt es ab.

Um der Funktion die Versprechensfunktionalität zur Verfügung zu stellen, müssen Sie nur das darin enthaltene Versprechungsobjekt zurückgeben.
 function myAsyncFunction(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xhr.statusText); xhr.send(); }); } 

Mit Hilfe. Dann werden Ausführungs- und Ablehnungshandler angehängt.

Methoden
  • Promise.all (iterable) - Wartet darauf, dass alle Versprechen für eines von ihnen ausgeführt oder abgelehnt werden. Gibt ein Versprechen zurück, das ausgeführt wird, nachdem alle Versprechen iterabel ausgeführt wurden. Für den Fall, dass eines der Versprechen abgelehnt wird, wird Promise.all ebenfalls abgelehnt.
  • Promise.allSettled (iterable) - Wartet auf die Erfüllung aller empfangenen Versprechen (sowohl Ausführung als auch Ablehnung). Gibt ein Versprechen zurück, das ausgeführt wird, wenn alle empfangenen Versprechen abgeschlossen (ausgeführt oder abgelehnt) sind, und enthält ein Array der Ergebnisse der Ausführung der empfangenen Versprechen.
  • Promise.race (iterable) - Wartet auf die Ausführung oder Ablehnung eines der erhaltenen Versprechen. Gibt ein Versprechen zurück, das mit dem Ergebnis der Ausführung des ersten ausgeführten oder abgelehnten Versprechens von .iterable ausgeführt oder abgelehnt wird.
  • Promise.reject (Grund) - Gibt ein aus einem Grund abgelehntes Versprechen zurück.
  • Promise.resolve (Wert) - Gibt das mit dem Ergebniswert ausgeführte Versprechen zurück.

Versprechen Prototyp
  • catch (onRejected) - Fügt eine Rückruffunktion hinzu, um die Ablehnung eines Versprechens zu behandeln, die ein neues Versprechen zurückgibt, das mit dem übergebenen Wert gemacht wurde, wenn es aufgerufen wird, oder den ursprünglichen Auflösungswert, wenn das Versprechen gemacht wurde.
  • then (onFulfilled, onRejected) - Fügt einen Handler für die Erfüllung und Ablehnung von Versprechen hinzu und gibt ein neues Versprechen zurück, das mit dem Wert des aufgerufenen Handlers oder dem ursprünglichen Wert ausgeführt wurde, wenn das Versprechen nicht verarbeitet wurde (d. h. wenn der entsprechende Handler für onFulfilled oder onRejected keine Funktion ist).


Erstellen einer asynchronen http-Anforderung:
 const URL = "https://getfestivo.com/v1/holidays?api_key=f8f42551-eb66-49d2-bcba-b8e42727ddfb&country=US&year=2019"; //  API      function asyncHttpRequest (url) { return new Promise((resolve, reject) => { //  promise if (url == undefined) //     url reject(new Error("Expected url and received nothing")); else { resolve(() => { fetch(url).then((response) => { //   return response.json(); //    JSON   }).then((myJson) => { return(console.log(myJson)); //      }); }); } } );} asyncHttpRequest(URL).then((result) => result(), (error) => console.log(error)); 



Weitere Beispiele und Informationen zu Versprechungen finden Sie in der offiziellen Dokumentation sowie in der Mozilla- Dokumentation .

Iteratoren


Die Verarbeitung jedes Elements in einer Sammlung ist eine sehr häufige Operation. JavaScript bietet verschiedene Möglichkeiten zum Durchlaufen einer Sammlung, von einer einfachen for-Schleife bis hin zu Map- (), Filter- () und Array-Verständnis. Iteratoren und Generatoren implementieren das Konzept der Aufzählung direkt in den Kern der Sprache und bieten einen Mechanismus zum Festlegen des Verhaltens für ... von Schleifen.

Ein Objekt ist ein Iterator, wenn es einzeln auf die Elemente der Sammlung zugreifen kann, während es seine aktuelle Position innerhalb dieser Sequenz verfolgt. In JavaScript ist ein Iterator ein Objekt, das eine next () -Methode bereitstellt, die das nächste Element einer Sequenz zurückgibt. Diese Methode gibt ein Objekt mit zwei Eigenschaften zurück: done und value.

Nach der Erstellung kann das Iteratorobjekt explizit verwendet werden, indem die next () -Methode aufgerufen wird.

Iterable - Dies ist ein Objekt, dessen Inhalt wiederholt werden kann.
Das iterierbare Objekt unterscheidet sich vom nicht iterierbaren darin, dass es eine spezielle Methode hat, die ein Objekt für den Zugriff zurückgibt, auf das ein spezielles Symbol verwendet wird: Symbol.iterator
 Iterable { [Symbol.iterator]() } 

Das Objekt, das die Methode zurückgibt, wird formal als Iterator bezeichnet.
Der Iterator hat nur eine next () -Methode
 Iterator { next(); } 

Dies gibt ein Objekt (nennen wir es itreratorResult) mit zwei Eigenschaften done und value zurück
 IteratorResult { done, value } 

done gibt an, ob die gesuchte Sequenz noch einen Wert enthält und der Wert das nächste Element der Sequenz enthält.


Nach der Initialisierung kann die next () -Methode aufgerufen werden, um nacheinander auf die Schlüssel-Wert-Paare im Objekt zuzugreifen.

Ein Objekt ist iterierbar, wenn es eine Methode zum Auflisten von Werten definiert, dh wie Werte im Konstrukt for..of aufgelistet werden. Einige integrierte Typen wie Array oder Map sind standardmäßig iterierbar, andere Typen wie Object hingegen nicht.

Um iterierbar zu sein, muss ein Objekt die Iteratormethode implementieren. Dies bedeutet, dass es (oder eines der Objekte in der Prototypenkette) eine Eigenschaft namens Symbol.iterator haben muss.

So sieht der Standard-Iterator aus:
 function makeIterator(array){ var nextIndex = 0; return { next: function(){ return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { done: true }; } } } 


Generatoren


Generatoren sind eine spezielle Art von Funktion, die wie eine Iteratorfabrik funktioniert. Eine Funktion wird zum Generator, wenn sie eine oder mehrere Yield-Anweisungen enthält und die Funktionssyntax * verwendet.

Generatoren sind eine neue Art von Funktion, die ihre Ausführung unterbrechen und ein Zwischenergebnis zurückgeben und die Ausführung später fortsetzen kann.

Schauen wir uns eine reguläre Funktion an, die etwas rechnet und ein Ergebnis zurückgibt:
 function myFunction (a) { a = a*2; a = a - 1; return a; } console.log(myFunction(5)); // 9 

Schauen Sie sich nun eine ähnliche Generatorfunktion an:
 function* generator(a) { a = a*2; yield a; a = a - 1; yield a; } var it = generator(5); console.log(it.next().value); // 10 console.log(it.next().value); // 9</i> 

Wie bereits erwähnt, können Generatoren ihre Ausführung unterbrechen und ein Zwischenergebnis zurückgeben. Dieses Beispiel zeigt, dass zum Zeitpunkt des ersten Aufrufs die Funktion, als ob sie ihre Ausführung beim ersten Haltepunktausbruch anhält, das Ergebnis des ersten Ausdrucks zurückgibt. Beim zweiten Aufruf wird die Funktion vom vorherigen Haltepunkt fortgesetzt und zum nächsten verschoben, wobei das Ergebnis des nächsten Ausdrucks zurückgegeben wird.

Funktionsgeneratoren bieten ein leistungsstarkes Werkzeug zum Schreiben komplexer sequentieller Funktionen.

Generatoren berechnen die Ergebnisse ihrer Ertragsausdrücke nach Bedarf, wodurch sie effizient mit Sequenzen mit hohem Rechenaufwand oder sogar mit unendlichen Sequenzen arbeiten können.

Die next () -Methode verwendet auch einen Wert, mit dem der interne Zustand des Generators geändert werden kann. Der an next () übergebene Wert wird als Ergebnis des letzten Ertragsausdrucks betrachtet, der den Generator angehalten hat.

Sie können den Generator zwingen, eine Ausnahme auszulösen, indem Sie seine throw () -Methode aufrufen und den Wert der Ausnahme übergeben, die als Parameter ausgelöst werden soll. Diese Ausnahme wird aus dem aktuell angehaltenen Kontext des Generators ausgelöst, als wäre die aktuell angehaltene Yield-Anweisung eine throw-Anweisung.

Wenn die Yield-Anweisung während der Verarbeitung der ausgelösten Ausnahme nicht auftritt, wird die Ausnahme oben über den Aufruf throw () übergeben, und das Ergebnis nachfolgender Aufrufe von next () wird als Eigenschaft true ausgeführt.

Generatoren haben eine Rückgabemethode (Wert), die den angegebenen Wert zurückgibt und den Generator stoppt.

Symbol


Symbol ist ein primitiver Datentyp, dessen Instanzen eindeutig und unveränderlich sind.

In der JavaScript-Laufzeit wird durch Aufrufen der Funktion Symbol () ein Symbolwert erstellt, der dynamisch einen anonymen und eindeutigen Wert erstellt. Die einzig sinnvolle Verwendung besteht darin, das Zeichen zu speichern und dann den gespeicherten Wert zu verwenden, um die Eigenschaft des Objekts zu erstellen.

Wenn ein Zeichen als Bezeichner in einer Eigenschaftszuweisung verwendet wird, ist die Eigenschaft (z. B. ein Zeichen) anonym. und auch nicht zählbar. Da die Eigenschaft nicht berechenbar ist, wird sie nicht in der Schleife "for (... in ...)" angezeigt, und da die Eigenschaft anonym ist, wird sie nicht im Ergebnisarray "Object.getOwnPropertyNames ()" angezeigt. Auf diese Eigenschaft kann mit dem Anfangswert des Symbols zugegriffen werden, mit dem sie erstellt wurde, oder indem das Ergebnisarray „Object.getOwnPropertySymbols ()“ durchlaufen wird.


So können Sie eine Zeicheneigenschaft erstellen:
 var user = { name: "Alex", [Symbol("password")]: "12hsK3I" } 

Verwenden Sie die Object.getOwnPropertySymbols (obj) -Eigenschaft, um ein Array von Zeichenobjekten abzurufen.
Verwenden Sie die Methoden Symbol.for () und Symbol.keyFor (), um auf eine beliebige Stelle in Ihrem Code zuzugreifen.

Weitere Informationen zum Datentyp Sumbol finden Sie in der offiziellen Dokumentation sowie in der Mozilla- Dokumentation .

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


All Articles