📜 ⬆️ ⬇️

Overview of ECMAScript 2016, 2017, and 2018 with examples

It is difficult to keep up with the innovations of different versions of ECMAScript, and even more difficult to find useful examples of their application without digging through the mountains of information. Therefore, today we publish the translation of the material, the author of which analyzed 18 new features of ECMAScript, including those that are already in the ES2016 and ES2017 standards, and also those that should appear in the ES2018 standard. The author of this article promises that everyone who reads it will learn a lot of interesting and useful things about new features of JavaScript.



ECMAScript 2016



â–Ť1. Array.prototype.includes ()


The includes method is a simple method of objects of the Array type, which allows you to find out if there is a certain element in the array (it, unlike indexOf , is also suitable for working with NaN values).


ECMAScript 2016 (ES7) - an example of using Array.prototype.includes ()
')
It is interesting that at first they wanted to call this method contains , but it turned out that this name was already used in Mootools, as a result, it was decided to use the name includes .

â–Ť2. Infix exponentiation operator


Mathematical operations, such as addition and subtraction, are implemented in JavaScript using infix operators, such as, respectively, “ + ” and “ - ”. There is also an infix operator that has found wide application in programming, which is used for exponentiation. Such an operator, looking like " ** ", was introduced in ECMAScript 2016, it can serve as a replacement for Math.pow() .


ECMAScript 2016 (ES7) - use infix exponentiation operator

ECMAScript 2017



▍1. Object.values ​​()


The Object.values() method is a new function that is similar to Object.keys() , but returns all the values ​​of the object's own properties, excluding any values ​​in the prototype chain.


ECMAScript 2017 (ES8) - using Object.values ​​()

â–Ť2. Object.entries ()


The Object.entries() method is similar to the Object.keys() method, but instead of returning only the keys, it returns both keys and values ​​as an array. This simplifies the execution of operations involving the use of objects in cycles, or operations to convert ordinary objects into objects of type Map .

Here is the first example of using this method.


ECMAScript 2017 (ES8) - using Object.entries () in loops

Here is a second example.


ECMAScript 2017 (ES8) - using Object.entries () to convert an object of type Object to an object of type Map

â–Ť3. Addition of lines to the set length


Objects of type String now have two new methods: String.prototype.padStart() and String.prototype.padEnd() . They allow you to attach to the lines, at their beginning or end, a number of characters to supplement the lines to a given length.

 'someString'.padStart(numberOfCharcters [,stringForPadding]); '5'.padStart(10) // '          5' '5'.padStart(10, '=*') //'=*=*=*=*=5' '5'.padEnd(10) // '5         ' '5'.padEnd(10, '=*') //'5=*=*=*=*=' 

This is convenient if you want to align the text, for example, when outputting to the console.

3.1 Example of working with padStart ()


In the following example, we have a list of numbers of different lengths. We want to add to the beginning of these numbers "0", and, thus, to make all of them consisting of 10 digits. It is necessary to accurately display them on the screen. In order to solve this problem, we can use the padStart(10, '0') command.


ECMAScript 2017 - an example of using padStart ()

3.2 An example of working with padEnd ()


The padEnd() method is very useful when displaying a set of lines of different lengths that need to be aligned along the right edge of the page.

The following example shows how to use the padEnd() , padStart() , and Object.entries() to form strings that look good when displayed on the screen.


ECMAScript 2017 - an example of using padEnd (), padStart () and Object.Entries ()

3.3. Using padStart () and padEnd () with emoticons and other double-byte characters


Emoticons and other two-byte characters are represented in Unicode encoding with sequences of several bytes. Therefore, the padStart() and padEnd() methods do not work with them as expected.

For example, suppose we want to make the length of the heart string equal to 10 characters by adding an emoticon ️ to it. The result, with the usual approach, will look like this:

 //   ,   5    2 ,   ,  ,   ,   'heart'.padStart(10, "️"); //    '️️heart' 

The problem here is that the heart with which we want to add a string is represented by the two-byte code '\u2764\uFE0F' . The word heart has a length of 5 characters and to supplement this line to length 10 we have only 5 free places. As a result, JS adds two emoticons to the string, using the code '\u2764\uFE0F' , which occupies four free spaces, which gives two heart icons. The last free space is filled with the first byte, the symbol with the code '\u2764' , which just gives the heart that looks different from the rest.

Here , by the way, is a page that can be used to work with Unicode characters.

â–Ť4. Object.getOwnPropertyDescriptors ()


This method returns all information (including information about getters and setters) for all properties of a given object. The main reason for adding this method is to allow small copies of objects to be created and to clone objects, creating new objects, while copying, among other things, getters and setters. The Object.assign() method does not know how. It allows you to make small copies of objects, but does not work with their getters and setters.

The following examples show the difference between Object.assign() and Object.getOwnPropertyDescriptors() , and also demonstrate how to use Object.defineProperties() to copy the original car object to a new object, ElectricCar . Here you can see that through the use of Object.getOwnPropertyDescriptors() , the discount function, which plays the role of both the getter and the setter, is also copied to the target object.

So, until Object.getOwnPropertyDescriptors() copying objects looked like this. Here you can see that when copying an object, data about getters and setters is lost.


Copying objects using Object.assign ()

Here's what the execution of the same operation looks like, but already using Object.getOwnPropertyDescriptors() .


ECMAScript 2017 (ES8) - using Object.getOwnPropertyDescriptors ()

â–Ť5. Trailing commas in function parameters


This is a small update that allows you to put a comma after the last parameter of the function. Why do you need it? For example, in order to help when working with tools like git blame , eliminating developers who make changes to the code from having to change (without much need in this case) the lines written by those who worked on this code before.

The following example shows the problem of editing the code and its solution using a comma, which is located behind the last parameter of the function.


ECMAScript 2017 (ES8) - a comma, set after the last parameter of the function, facilitates code editing

â–Ť6. Async / Await design


I would call this innovation the most important and the most useful. Asynchronous functions allow you to get rid of the so-called “hell callbacks” and improve the appearance and readability of the code.
The async tells the JavaScript interpreter that the function declared with this keyword needs to be perceived in a special way. The system pauses, reaching the await keyword in this function. She considers that the expression after await returns a promise and waits for permission or rejection of this promise before continuing.

In the following example, the getAmount() function calls two asynchronous functions, getUser() and getBankBalance() . This can be done in promise, but using the async / await construction makes it easier and more elegant to solve this problem.


ECMAScript 2017 (ES 8) - a simple example of using the Async / Await construction

6.1. Asynchronous Functions and Promise Returns


If you expect a result from a function declared using the async , you will need to use the expression promis .then() to get this result.

In the following example, we want to output the result to the console using the console.log() command, but this needs to be done outside the doubleAndAdd() function. Therefore, we need to wait using .then() to transfer the result to console.log() .


ECMAScript 2017 (ES 8) - demonstration of return promise with the async / await construct

6.2. Parallel function calls using async / await


In the previous example, we use the await keyword twice, each time waiting for the operation to complete for one second (total waiting time is 2 seconds). Instead, we can parallelize the execution of tasks, since a and b are independent of each other. This can be done using the Promise.all() construct.


ECMAScript 2017 (ES 8) - using Promise.all for parallel execution of await commands

6.3. Error handling when using async / await construction


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

Option 1: use try / catch inside a function


ECMAScript 2017 - use try / catch inside async / await construction

Option 2: use catch in each await expression

Since each await expression returns a promise, you can catch errors in each such expression.


ECMAScript 2017 - Use the catch construct with each await expression

Option 3: use the catch construct for the entire async / await function


ECMAScript 2017 - interception of errors in the entire asynchronous function

ECMAScript 2018




ECMAScript 2018 is now at the stage of final draft, the standard is expected in June-July 2018. All features discussed below are at Stage-4 and will become part of ECMAScript 2018.

â–Ť1. Shared memory and atomic operations


Shared memory and atomic operations are a terrific, highly advanced feature affecting the core of JS engines.

The main idea of ​​this feature is to allow JS-developers to write high-performance parallel applications, to give them the ability to manage memory independently, without giving all the aspects of this task to the JS engine.

This is implemented using a global object of a new type called SharedArrayBuffer . Its main task is to store data in a shared memory space. As a result, such data can be shared between the main JS stream and web worker threads.

Until now, if we needed to organize data exchange between the main thread and the web worker, we had to create copies of the data and send them using the postMessage() function. Now everything will not be the same as before.

By using SharedArrayBuffer different streams can access data almost instantly. However, sharing memory from different streams can cause a race condition. In order to avoid this state, a global Atomics object is provided. It provides various methods for blocking shared memory for the duration of operations with it from a particular thread. It also provides methods for safely updating data in shared memory.

Usually this feature is not recommended to be used directly, saying that it would be better to use libraries built on the basis of the SharedArrayBuffer . However, such libraries have not yet been written.

If you are interested in this topic - here , here and here - some useful materials.

â–Ť2. Eliminate the limitations of tagged pattern strings


To begin with, let's look at the concept of “tagged template string” (or “tagged template”) in order to better understand this new feature.

In ES2015 + there is a feature called a tagged template that allows developers to customize string interpolation. For example, with the standard approach, it looks like this.


Standard use of patterned strings

When using tagged templates, you can write a function that takes, as parameters, an invariable part of a string literal, for example, [ 'Hello ', '!' ] [ 'Hello ', '!' ] and substitution variables, for example, [ 'Raja'] . For example, let it be a greet function. Such a function can return what the developer needs.

The following example shows how our own tag expression, a function, appends a greeting to a string based on the time of day (for example, “Good Morning!” Or “Good afternoon”) and returns the finished string.


An example of a tagged expression, a function that demonstrates custom string addition

After learning about tagged template strings, many people seek to use this feature in various fields, for example, to work with commands in a terminal or when creating a URL to execute HTTP requests. However, there is one important limitation to consider. It lies in the fact that ES2015 and ES2016 allow you to use only control sequences like "\u" (unicode) , "\x"(hexadecimal) , which form something that is understandable to the system, for example, `\u00A9` or \u{2F804} or \xA9 .

Therefore, if there is a tagged function, inside which rules from another area are used (for example, when working with a terminal), where you may need to use something like \ubla123abla that does not look like a correct code from the system’s point of view, an error message will appear.

In ES2018, restrictions are relaxed. Now you can use constructions that look like wrong control sequences, returning values ​​in the object, one property of which (“cooked” in our example) contains undefined , and the second (“raw”) contains what we need.

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

â–Ť3. DotAll regular expression flag


Now, when using regular expressions, although it is believed that the dot character matches any single character, it does not match newline characters like \n \r \f and so on.

For example, before this innovation, everything looked like this:

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

With this improvement, the dot now matches absolutely any character. In order for the old regular expressions to continue to work as before, when creating regular expressions that follow the new rules, you need to use the \s flag.

 //ECMAScript 2018 /first.second/s.test('first\nsecond'); //true -    /s 

Here is the API of this proposal from the documentation.


ECMAScript 2018 - now, thanks to the / s flag, you can make the dot in regular expressions match absolutely all characters, including \ n

â–Ť4. Capturing Named Groups in Regular Expressions


This enhancement is a useful regular expression feature that exists in other languages ​​like Python and Java. These are named groups. This feature allows developers to write regular expressions with assignment of names (identifiers) in the format (?<name>...) for groups. This name makes it easier to work with groups.

4.1. Basic example of working with named groups


In the following example, we use the names (?<year>) , (?<month>) and (?day) to group the different parts of the date we work with using a regular expression. The final object in this approach will contain the groups property, which will have the year , month and day properties with the corresponding values.


ECMAScript 2018 - an example of working with named groups

4.2. Using named groups inside a regular expression


We can use constructions of the form \k<group name> to refer to groups within the regular expression itself. This technique is demonstrated in the following example.


ECMAScript 2018 - using named groups within a regular expression using the \ k <group name> construct

4.3. Using Named Groups in String.prototype.replace ()


Now the ability to use named groups is built into the replace() string method. This allows, for example, to organize a permutation of words in lines. For example, here's how to change the string "firstName, lastName" to "lastName, firstName" .


ECMAScript 2018 - using named regular expression groups in the string replace () method

â–Ť5. Working with object properties using the rest operator


The rest operator, which looks like three points, allows you to retrieve the properties of an object that have not yet been extracted from it.

5.1. Retrieving from the object only the necessary properties



ECMAScript 2018 - Destructuring an Object Using the Rest Operator

5.2. Remove unwanted properties of objects



ECMAScript 2018 - removing unnecessary properties of objects

â–Ť6. Working with properties of objects using the spread operator


The spread operator also looks like three points. The difference between it and the rest operator is that it is used to create new objects.

The spread operator is used on the right side of an expression with an assignment sign. The rest operator is used on the left side of the expression.


ECMAScript 2018 - creating an object using the rest operator

â–Ť7. Retrospective check in regular expressions


A retrospective check in regular expressions allows you to find out if a certain string exists immediately before some other string.

Now, in order to make a positive retrospective test, you can use a group of the form (?<=…) (question mark, less sign and equal sign).

Further, you can use a group of the form (?>!…) (question mark, less sign, exclamation mark) to perform a negative retrospective check. The search with this approach is continued only if there is no expression in brackets to the left of the current position in the text.

Consider an example of a positive retrospective test. Suppose we need to check whether the # character is # front of the word winning (that is, we are interested in the construction of the form #winning ), while we need the regular expression to return only the string "winning". Here is how you can achieve this.


ECMAScript 2018 - using the construct (? <= ...) for positive retrospective verification

Consider an example of negative retrospective verification. Suppose we need to extract from the string the numbers preceded by the € sign, but not the $ sign. Here's how to do it.


EMAScript 2018 - using the construct (? <! ...) for negative retrospective verification

â–Ť8. Using Unicode escape sequences in regular expressions


Previously, writing regular expressions to analyze Unicode characters was not easy. Constructions of the form \w , \W , \d helped only in working with Latin characters and numbers. And what about the characters of other languages, like Hindi or Greek?

It is in such situations that the use of Unicode escape sequences in regular expressions will be useful. Unicode is known to have metadata for each character; this metadata is used to group or describe the characteristics of different characters.

Unicode ( — हिन्दी, , , ) Script Devanagari , , Script_Extensions , . Script=Devanagari .

Unicode- Devanagari , , , , .

ECMAScript 2018 \p{Script=Devanagari} . .


ECMAScript 2018 — Unicode-

, Script_Extensions ( Script ) Greek . Script_Extensions=Greek Script=Greek .

\p{Script=Greek} .


ECMAScript 2018 —

, Unicode Emoji , Emoji_Component , Emoji_Presentation , Emoji_Modifier , Emoji_Modifier_Base true . , Emoji .

, \p{Emoji} \p{Emoji_Modifier} . .


ECMAScript 2018 —

, , , P ( \P ) p ( \p ) .

â–Ť9. Promise.prototype.finally()


finally() — Promise . , resolve() reject() , , , , . finally() - , .

.


ECMAScript 2018 — finally() resolve()


ECMAScript 2018 — finally() reject()


ECMAScript 2018 — finally()


ECMAScript 2018 — finally() catch()

â–Ť10.


— . , .

for-await-of , , ( , ) . , .


ECMAScript 2018 — for-await-of

Results


ES2016, ES2017 ES2018, . , , JavaScript .

! ES2016, ES2017 ES2018 ?

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


All Articles