Hier finden Sie Beispiele für alles Neue in ECMAScript 2016, 2017 und 2018

Es ist schwierig zu verfolgen, was in JavaScript (ECMAScript) neu ist. Und es ist noch schwieriger, nützliche Codebeispiele zu finden.

In diesem Artikel werde ich daher alle 18 Funktionen behandeln, die in den fertigen Vorschlägen des TC39 aufgeführt sind, die in ES2016, ES2017 und ES2018 (endgültiger Entwurf) hinzugefügt wurden, und sie mit nützlichen Beispielen zeigen.

Dies ist ein ziemlich langer Beitrag, der aber leicht zu lesen sein sollte. Stellen Sie sich dies als " Netflix-Binge-Reading" vor. Am Ende verspreche ich, dass Sie eine Menge Wissen über all diese Funktionen haben werden.

OK, lassen Sie uns diese nacheinander durchgehen.

1. Array.prototype.includes

includesist eine einfache Beispiel - Methode auf dem Array und hilft , wenn ein Element im Array (einschließlich ist leicht zu finden , im NaNGegensatz zu indexOf).

Wissenswertes: Die JavaScript-Spezifikation wollte es benennen contains, aber dies wurde anscheinend bereits von Mootools verwendet, also verwendeten sie es includes.

2. Potenzierung infix operator

Mathematische Operationen wie Addition und Subtraktion haben Infixoperatoren wie +und -, respectively. Ähnlich wie bei ihnen wird der **Infix-Operator üblicherweise für die Exponentenoperation verwendet. In ECMAScript 2016 ** wurde das anstelle von eingeführt Math.pow.

1. Object.values ​​()

Object.values()ist eine neue Funktion, die ähnlich ist, Object.keys()aber alle Werte der eigenen Eigenschaften des Objekts mit Ausnahme aller Werte in der prototypischen Kette zurückgibt.

2. Object.entries ()

Object.entries()ist verwandt mit Object.keys, aber anstatt nur Schlüssel zurückzugeben, werden sowohl Schlüssel als auch Werte auf Array-Weise zurückgegeben. Dies macht es sehr einfach, Objekte in Schleifen zu verwenden oder Objekte in Maps zu konvertieren.

Beispiel 1:

Beispiel 2:

3. Stringauffüllung

String - String.prototype.padStart und String.prototype.padEnd- wurden zwei Instanzmethoden hinzugefügt, mit denen entweder eine leere Zeichenfolge oder eine andere Zeichenfolge an den Anfang oder das Ende der ursprünglichen Zeichenfolge angehängt / vorangestellt werden kann.

'someString'.padStart(numberOfCharcters [,stringForPadding]); '5'.padStart(10) // ' 5' '5'.padStart(10, '=*') //'=*=*=*=*=5' '5'.padEnd(10) // '5 ' '5'.padEnd(10, '=*') //'5=*=*=*=*='
Dies ist praktisch, wenn wir Dinge in Szenarien wie hübscher Druckanzeige oder Terminaldruck ausrichten möchten.

3.1 padStart Beispiel:

Im folgenden Beispiel haben wir eine Liste von Nummern unterschiedlicher Länge. Wir möchten "0" voranstellen, damit alle Elemente zu Anzeigezwecken dieselbe Länge von 10 Stellen haben. Wir können dies padStart(10, '0')leicht erreichen.

3.2 padEnd Beispiel:

padEnd Dies ist sehr praktisch, wenn wir mehrere Elemente unterschiedlicher Länge drucken und sie richtig ausrichten möchten.

Das folgende Beispiel ist ein gutes realistisches Beispiel dafür padEnd, wie padStartund Object.entriesalle zusammenkommen, um eine schöne Ausgabe zu erzielen.

const cars = { '?BMW': '10', '?Tesla': '5', '?Lamborghini': '0' } Object.entries(cars).map(([name, count]) => { //padEnd appends ' -' until the name becomes 20 characters //padStart prepends '0' until the count becomes 3 characters. console.log(`${name.padEnd(20, ' -')} Count: ${count.padStart(3, '0')}`) }); //Prints.. // ?BMW - - - - - - - Count: 010 // ?Tesla - - - - - - Count: 005 // ?Lamborghini - - - Count: 000

3.3 ⚠️ padStart und padEnd auf Emojis und anderen Doppelbyte-Zeichen

Emojis und andere Doppelbyte-Zeichen werden mit mehreren Unicode-Bytes dargestellt. PadStart und padEnd funktionieren also möglicherweise nicht wie erwartet! ⚠️

Zum Beispiel: Nehmen wir an, wir versuchen, die Zeichenfolge aufzufüllen heart, um 10Zeichen mit dem Emoji zu erreichen . Das Ergebnis sieht wie folgt aus:

//Notice that instead of 5 hearts, there are only 2 hearts and 1 heart that looks odd! 'heart'.padStart(10, "❤️"); // prints.. '❤️❤️❤heart'

Dies liegt daran, dass ❤️ 2 Codepunkte lang ist ( '\u2764\uFE0F')! Das Wort heartselbst besteht aus 5 Zeichen, sodass wir nur noch 5 Zeichen zum Auffüllen haben. Was also passiert ist, dass JS zwei Herzen mit '\u2764\uFE0F'auffüllt und das ❤️❤️ erzeugt. Für das letzte verwendet es einfach das erste Byte des Herzens \u2764, das ❤ erzeugt

Am Ende haben wir also: ❤️❤️❤heart

PS: Über diesen Link können Sie Unicode-Zeichenkonvertierungen überprüfen.

4. Object.getOwnPropertyDescriptors

Diese Methode gibt alle Details (einschließlich Getter- getund Setter- setMethoden) für alle Eigenschaften eines bestimmten Objekts zurück. Die Hauptmotivation, dies hinzuzufügen, besteht darin, das flache Kopieren / Klonen eines Objekts in ein anderes Objekt zu ermöglichendas kopiert auch Getter- und Setter-Funktionen im Gegensatz zu Object.assign.

Object.assign flat kopiert alle Details mit Ausnahme der Getter- und Setter-Funktionen des ursprünglichen Quellobjekts.

Das folgende Beispiel zeigt den Unterschied zwischen Object.assignund Object.getOwnPropertyDescriptorszusammen mit Object.definePropertiesdem Kopieren eines Originalobjekts Carin ein neues Objekt ElectricCar. Sie werden sehen , dass durch die Verwendung Object.getOwnPropertyDescriptors, discountGetter und Setter - Funktionen auch in das Zielobjekt kopiert werden.

VOR…

NACH…

var Car = { name: 'BMW', price: 1000000, set discount(x) { this.d = x; }, get discount() { return this.d; }, }; //Print details of Car object's 'discount' property console.log(Object.getOwnPropertyDescriptor(Car, 'discount')); //prints.. // { // get: [Function: get], // set: [Function: set], // enumerable: true, // configurable: true // } //Copy Car's properties to ElectricCar using Object.assign const ElectricCar = Object.assign({}, Car); //Print details of ElectricCar object's 'discount' property console.log(Object.getOwnPropertyDescriptor(ElectricCar, 'discount')); //prints.. // { // value: undefined, // writable: true, // enumerable: true, // configurable: true // } //⚠️Notice that getters and setters are missing in ElectricCar object for 'discount' property !?? //Copy Car's properties to ElectricCar2 using Object.defineProperties //and extract Car's properties using Object.getOwnPropertyDescriptors const ElectricCar2 = Object.defineProperties({}, Object.getOwnPropertyDescriptors(Car)); //Print details of ElectricCar2 object's 'discount' property console.log(Object.getOwnPropertyDescriptor(ElectricCar2, 'discount')); //prints.. // { get: [Function: get], ?????? // set: [Function: set], ?????? // enumerable: true, // configurable: true // } // Notice that getters and setters are present in the ElectricCar2 object for 'discount' property!

5. Add trailing commas in the function parameters

Dies ist ein kleines Update, das es uns ermöglicht, nach dem letzten Funktionsparameter nachgestellte Kommas zu setzen. Warum? Um mit Tools wie Git Blame zu helfen, um sicherzustellen, dass nur neue Entwickler beschuldigt werden.

Das folgende Beispiel zeigt das Problem und die Lösung.

Hinweis: Sie können Funktionen auch mit nachgestellten Kommas aufrufen!

6. Async / Warten

This, by far, is the most important and most useful feature if you ask me. Async functions allows us to not deal with callback hell and make the entire code look simple.

The async keyword tells the JavaScript compiler to treat the function differently. The compiler pauses whenever it reaches the await keyword within that function. It assumes that the expression after await returns a promise and waits until the promise is resolved or rejected before moving further.

In the example below, the getAmount function is calling two asynchronous functions getUser and getBankBalance . We can do this in promise, but using async await is more elegant and simple.

6.1 Async functions themselves return a Promise.

If you are waiting for the result from an async function, you need to use Promise’s then syntax to capture its result.

In the following example, we want to log the result using console.log but not within the doubleAndAdd. So we want to wait and use then syntax to pass the result to console.log .

6.2 Calling async/await in parallel

In the previous example we are calling await twice, but each time we are waiting for one second (total 2 seconds). Instead we can parallelize it since a and b are not dependent on each other using Promise.all.

6.3 Error handling async/await functions

There are various ways to handle errors when using async await.

Option 1 — Use try catch within the function

//Option 1 - Use try catch within the function async function doubleAndAdd(a, b) { try { a = await doubleAfter1Sec(a); b = await doubleAfter1Sec(b); } catch (e) { return NaN; //return something } return a + b; } //?Usage: doubleAndAdd('one', 2).then(console.log); // NaN doubleAndAdd(1, 2).then(console.log); // 6 function doubleAfter1Sec(param) { return new Promise((resolve, reject) => { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }

Option 2— Catch every await expression

Da jeder awaitAusdruck ein Versprechen zurückgibt, können Sie Fehler in jeder Zeile abfangen, wie unten gezeigt.

//Option 2 - *Catch* errors on every await line //as each await expression is a Promise in itself async function doubleAndAdd(a, b) { a = await doubleAfter1Sec(a).catch(e => console.log('"a" is NaN')); // ? b = await doubleAfter1Sec(b).catch(e => console.log('"b" is NaN')); // ? if (!a || !b) { return NaN; } return a + b; } //?Usage: doubleAndAdd('one', 2).then(console.log); // NaN and logs: "a" is NaN doubleAndAdd(1, 2).then(console.log); // 6 function doubleAfter1Sec(param) { return new Promise((resolve, reject) => { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }

Option 3 - Erfassen Sie die gesamte Async-Wait-Funktion

//Option 3 - Dont do anything but handle outside the function //since async / await returns a promise, we can catch the whole function's error async function doubleAndAdd(a, b) { a = await doubleAfter1Sec(a); b = await doubleAfter1Sec(b); return a + b; } //?Usage: doubleAndAdd('one', 2) .then(console.log) .catch(console.log); // ??? { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }
ECMAScript befindet sich derzeit im endgültigen Entwurf und wird im Juni oder Juli 2018 veröffentlicht. Alle unten aufgeführten Funktionen befinden sich in Phase 4 und werden Teil von ECMAScript 2018 sein.

1. Shared Memory und Atomics

Dies ist eine riesige, ziemlich erweiterte Funktion und eine Kernverbesserung für JS-Engines.

Die Hauptidee besteht darin, eine Art Multithreading-Funktion in JavaScript zu integrieren, damit JS-Entwickler in Zukunft leistungsstarke, gleichzeitige Programme schreiben können, indem sie den Speicher selbst verwalten können, anstatt die JS-Engine den Speicher verwalten zu lassen.

This is done by a new type of a global object called SharedArrayBuffer that essentially stores data in a sharedmemory space. So this data can be shared between the main JS thread and web-worker threads.

Until now, if we want to share data between the main JS thread and web-workers, we had to copy the data and send it to the other thread using postMessage . Not anymore!

You simply use SharedArrayBuffer and the data is instantly accessible by both the main thread and multiple web-worker threads.

Das Teilen des Speichers zwischen Threads kann jedoch zu Race-Bedingungen führen. Um Rennbedingungen zu vermeiden, wird das globale Objekt „ Atomics “ eingeführt. Atomics bietet verschiedene Methoden zum Sperren des gemeinsam genutzten Speichers, wenn ein Thread seine Daten verwendet. Es bietet auch Methoden zum sicheren Aktualisieren solcher Daten in diesem gemeinsam genutzten Speicher.

Es wird empfohlen, diese Funktion über eine Bibliothek zu verwenden. Derzeit sind jedoch keine Bibliotheken auf dieser Funktion aufgebaut.

Wenn Sie interessiert sind, empfehle ich zu lesen:

  1. Vom Arbeiter zum gemeinsamen Gedächtnis y - lucasfcosta
  2. Ein Cartoon-Intro zu SharedArrayBuffers - Lin Clark
  3. Shared Memory und Atomics - Dr. Axel Rauschmayer

2. Markierte Template-Literal-Einschränkung entfernt

First, we need to clarify what a “Tagged Template literal” is so we can understand this feature better.

In ES2015+, there is a feature called a tagged template literal that allows developers to customize how strings are interpolated. For example, in the standard way strings are interpolated like below…

In the tagged literal, you can write a function to receive the hardcoded parts of the string literal, for example [ ‘Hello ‘, ‘!’ ] , and the replacement variables, for example,[ 'Raja'] , as parameters into a custom function (for example greet ), and return whatever you want from that custom function.

The below example shows that our custom “Tag” function greet appends time of the day like “Good Morning!” “Good afternoon,” and so on depending on the time of the day to the string literal and returns a custom string.

//A "Tag" function returns a custom string literal. //In this example, greet calls timeGreet() to append Good //Morning/Afternoon/Evening depending on the time of the day. function greet(hardCodedPartsArray, ...replacementPartsArray) { console.log(hardCodedPartsArray); //[ 'Hello ', '!' ] console.log(replacementPartsArray); //[ 'Raja' ] let str = ''; hardCodedPartsArray.forEach((string, i) => { if (i < replacementPartsArray.length) { str += `${string} $`; } else { str += `${string} ${timeGreet()}`; //<-- append Good morning/afternoon/evening here } }); return str; } //?Usage: const firstName = 'Raja'; const greetings = greet`Hello ${firstName}!`; //??<-- Tagged literal console.log(greetings); //'Hello Raja! Good Morning!' ? function timeGreet() { const hr = new Date().getHours(); return hr < 12 ? 'Good Morning!' : hr < 18 ? 'Good Afternoon!' : 'Good Evening!'; }

Now that we discussed what “Tagged” functions are, many people want to use this feature in different domains, like in Terminal for commands and HTTP requests for composing URIs, and so on.

⚠️The problem with Tagged String literal

The problem is that ES2015 and ES2016 specs doesn’t allow using escape characters like “\u” (unicode), “\x”(hexadecimal) unless they look exactly like `\u00A9` or \u{2F804} or \xA9.

So if you have a Tagged function that internally uses some other domain’s rules (like Terminal’s rules), that may need to use \ubla123abla that doesn’t look like \u0049 or \u{@F804}, then you would get a syntax error.

In ES2018, the rules are relaxed to allow such seemingly invalid escape characters as long as the Tagged function returns the values in an object with a “cooked” property (where invalid characters are “undefined”), and then a “raw” property (with whatever you want).

function myTagFunc(str) { return { "cooked": "undefined", "raw": str.raw[0] } } var str = myTagFunc `hi \ubla123abla`; //call myTagFunc str // { cooked: "undefined", raw: "hi \\unicode" }

3. “dotall” flag for Regular expression

Currently in RegEx, although the dot(“.”) is supposed to match a single character, it doesn’t match new line characters like \n \r \f etc.

For example:

//Before /first.second/.test('first\nsecond'); //false

This enhancement makes it possible for the dot operator to match any single character. In order to ensure this doesn’t break anything, we need to use \s flag when we create the RegEx for this to work.

//ECMAScript 2018 /first.second/s.test('first\nsecond'); //true Notice: /s ?? 

Here is the overall API from the proposal doc:

4. RegExp Named Group Captures ?

This enhancement brings a useful RegExp feature from other languages like Python, Java and so on called “Named Groups.” This features allows developers writing RegExp to provide names (identifiers) in the format(?...) for different parts of the group in the RegExp. They can then use that name to grab whichever group they need with ease.

4.1 Basic Named group example

In the below example, we are using (?) (?) and (?) names to group different parts of the date RegEx. The resulting object will now contain a groups property with properties year, month , and day with corresponding values.

4.2 Using Named groups inside regex itself

We can use the \k format to back reference the group within the regex itself. The following example shows how it works.

4.3 Using named groups in String.prototype.replace

The named group feature is now baked into String’s replace instance method. So we can easily swap words in the string.

For example, change “firstName, lastName” to “lastName, firstName”.

5. Rest properties for Objects

Rest operator ... (three dots) allows us to extract Object properties that are not already extracted.

5.1 You can use rest to help extract only properties you want

5.2 Even better, you can remove unwanted items! ??

6. Spread properties for Objects

Spread properties also look just like rest properties with three dots ... but the difference is that you use spread to create (restructure) new objects.

Tip: the spread operator is used in the right side of the equals sign. The rest are used in the left-side of the equals sign.

7. RegExp Lookbehind Assertions

This is an enhancement to the RegEx that allows us to ensure some string exists immediately *before* some other string.

You can now use a group (?<=…) (question mark, less than, equals) to look behind for positive assertion.

Further, you can use (?(question mark, less than, exclamation), to look behind for a negative assertion. Essentially this will match as long as the -ve assertion passes.

Positive Assertion: Let’s say we want to ensure that the # sign exists before the word winning (that is: #winning) and want the regex to return just the string “winning”. Here is how you’d write it.

Original text


Negative Assertion: Let’s say we want to extract numbers from lines that have € signs and not $ signs before those numbers.

8. RegExp Unicode Property Escapes

It was not easy to write RegEx to match various unicode characters. Things like \w , \W , \d etc only match English characters and numbers. But what about numbers in other languages like Hindi, Greek, and so on?

That’s where Unicode Property Escapes come in. It turns out Unicode adds metadata properties for each symbol (character) and uses it to group or characterize various symbols.

For example, Unicode database groups all Hindi characters(हिन्दी) under a property called Script with value Devanagari and another property called Script_Extensions with the same value Devanagari. So we can search for Script=Devanagari and get all Hindi characters.

Devanagari can be used for various Indian languages like Marathi, Hindi, Sanskrit, and so on.

Starting in ECMAScript 2018, we can use \p to escape characters along with {Script=Devanagari} to match all those Indian characters. That is, we can use: \p{Script=Devanagari} in the RegEx to match all Devanagari characters.

//The following matches multiple hindi character /^\p{Script=Devanagari}+$/u.test('हिन्दी'); //true //PS:there are 3 hindi characters h

Similarly, Unicode database groups all Greek characters under Script_Extensions (and Script ) property with the value Greek . So we can search for all Greek characters using Script_Extensions=Greek or Script=Greek .

That is, we can use: \p{Script=Greek} in the RegEx to match all Greek characters.

//The following matches a single Greek character /\p{Script_Extensions=Greek}/u.test('π'); // true

Further, the Unicode database stores various types of Emojis under the boolean properties Emoji, Emoji_Component, Emoji_Presentation, Emoji_Modifier, and Emoji_Modifier_Base with property values as `true`. So we can search for all Emojis by simply selecting Emoji to be true.

That is, we can use: \p{Emoji} ,\Emoji_Modifier and so on to match various kinds of Emojis.

The following example will make it all clear.

//The following matches an Emoji character /\p{Emoji}/u.test('❤️'); //true //The following fails because yellow emojis don't need/have Emoji_Modifier! /\p{Emoji}\p{Emoji_Modifier}/u.test('✌️'); //false //The following matches an emoji character\p{Emoji} followed by \p{Emoji_Modifier} /\p{Emoji}\p{Emoji_Modifier}/u.test('✌?'); //true //Explaination: //By default the victory emoji is yellow color. //If we use a brown, black or other variations of the same emoji, they are considered //as variations of the original Emoji and are represented using two unicode characters. //One for the original emoji, followed by another unicode character for the color. // //So in the below example, although we only see a single brown victory emoji, //it actually uses two unicode characters, one for the emoji and another // for the brown color. // //In Unicode database, these colors have Emoji_Modifier property. //So we need to use both \p{Emoji} and \p{Emoji_Modifier} to properly and //completely match the brown emoji. /\p{Emoji}\p{Emoji_Modifier}/u.test('✌?'); //true

Lastly, we can use capital "P”(\P ) escape character instead of small p (\p ), to negate the matches.

References:

  1. ECMAScript 2018 Proposal
  2. //mathiasbynens.be/notes/es-unicode-property-escapes

8. Promise.prototype.finally()

finally() is a new instance method that was added to Promise. The main idea is to allow running a callback after either resolve or reject to help clean things up. The finally callback is called without any value and is always executed no matter what.

Let’s look at various cases.

9. Asynchronous Iteration

This is an *extremely* useful feature. Basically it allows us to create loops of async code with ease!

This feature adds a new “for-await-of” loop that allows us to call async functions that return promises (or Arrays with a bunch of promises) in a loop. The cool thing is that the loop waits for each Promise to resolve before doing to the next loop.

That’s pretty much it!

If this was useful, please click the clap ? button down below a few times to show your support! ⬇⬇⬇ ??

My Other Posts

//medium.com/@rajaraodv/latest

Related ECMAScript 2015+ posts

  1. Check out these useful ECMAScript 2015 (ES6) tips and tricks
  2. 5 JavaScript “Bad” Parts That Are Fixed In ES6
  3. Is “Class” In ES6 The New “Bad” Part?