📜 ⬆️ ⬇️

JavaScript Guide, Part 8: ES6 Standard Feature Overview

Today, in the eighth part of the translation of the JavaScript manual, we will review the language features that appeared in it after the release of the ES6 standard. We, in one way or another, have come across many of these opportunities before, somewhere dwelling on them in more detail, somewhere taking for granted. This section of the guide is intended, along with the disclosure of some topics that we have not previously dealt with, to streamline the knowledge of the novice developer in the field of modern JavaScript.

→ Part 1: first program, language features, standards
→ Part 2: code style and program structure
→ Part 3: Variables, Data Types, Expressions, Objects
→ Part 4: Functions
→ Part 5: Arrays and Loops
→ Part 6: Exceptions, Semicolon, Pattern Literals
→ Part 7: strict mode, this keyword, events, modules, mathematical calculations
→ Part 8: ES6 feature overview
→ Part 9: Overview of ES7, ES8, and ES9 Capabilities



About ES6


The ES6 standard, which it would be more correct to call ES2015 or ECMAScript 2015 (these are its official names, although everyone calls it ES6), appeared 4 years after the release of the previous standard - ES5.1. The development of all that is included in the standard ES5.1, took about ten years. Nowadays, everything that has appeared in this standard has become the familiar tools of a JS developer. It should be noted that ES6 made the most serious changes to the language (maintaining backward compatibility with its previous versions). In order to estimate the scale of these changes, it can be noted that the size of the document describing the ES5 standard is approximately 250 pages, and the ES6 standard is described in a document consisting of approximately 600 pages already.
')
The list of the most important innovations of the ES2015 standard can include the following:


Consider these possibilities.

Arrow functions


Arrow functions have changed the look and feel of JavaScript code. In terms of appearance, using them makes function declarations shorter and easier. Here is the declaration of the usual function.

 const foo = function foo() { //... } 

But almost the same (although not completely similar to the above) switch function.

 const foo = () => { //... } 

If the body of the arrow function consists of only one line, the result of which you need to return from this function, then it is written even shorter.

 const foo = () => doSomething() 

If the switch function takes only one parameter, you can write it as follows.

 const foo = param => doSomething(param) 

It should be noted that with the advent of switch functions, the usual functions have not gone away, they can still be used in the code, they work the same way as before.

Features of the keyword this in the switch functions


The switch functions do not have their own value of this ; they inherit it from the execution context.

This eliminates the problem that, when using normal functions, had to be used, to save the context, to use constructions like var that = this . However, as was shown in the previous parts of the manual, this change has a serious effect on the features of working with switch functions and on the scope of their application.

Promises


Promises allow you to get rid of a well-known problem, called “hell of callbacks,” although their use implies the use of quite complex structures. This problem was solved in the ES2017 standard with the advent of async/await , which is based on promises.

JavaScript developers used promises even before the appearance of the ES2015 standard, using various libraries for this (for example, jQuery, q, deferred.js, vow). This indicates the importance and relevance of this mechanism. Different libraries implement it differently, the emergence of a standard in this area can be considered a very positive fact.
Here is the code written using callbacks (callbacks).

 setTimeout(function() { console.log('I promised to run after 1s') setTimeout(function() {   console.log('I promised to run after 2s') }, 1000) }, 1000) 

Using promises, this can be rewritten as follows.

 const wait = () => new Promise((resolve, reject) => { setTimeout(resolve, 1000) }) wait().then(() => { console.log('I promised to run after 1s') return wait() }) .then(() => console.log('I promised to run after 2s')) 

Generators


Generators are special functions that can suspend their own execution and resume it. This allows, while the generator is in a standby state, to be executed by another code.

The generator independently decides that it needs to pause and allow another code, “waiting” for its turn, to execute. In this case, the generator has the opportunity to continue its execution after the operation, the results of which it is waiting for, will be completed.

All this is done thanks to the single simple keyword yield . When this keyword is found in the generator, its execution is suspended.
A generator can contain multiple lines with this keyword, suspending its own execution several times. Generators are declared using the *function construction. This asterisk in front of the word function should not be taken for something like a pointer dereference operator used in languages ​​like C, C ++ or Go.

Generators signify the emergence of a new JavaScript programming paradigm. In particular, they enable the two-way exchange of data between the generator and other code, allow you to create long-lived while loops that do not “hang” the program.

Consider an example illustrating the features of the generators. Here is the generator itself.

 function *calculator(input) {   var doubleThat = 2 * (yield (input / 2))   var another = yield (doubleThat)   return (input * doubleThat * another) } 

With this command we initialize it.

 const calc = calculator(10) 

Then we refer to its iterator.

 calc.next() 

This command starts an iterator, it returns such an object.

 { done: false value: 5 } 

Here is the following. The code executes a function using the input value passed to the generator constructor. The generator code is executed until the yield keyword is found in it. At this point, it returns the result of dividing input by 2 , which, since input equals 10 , gives the number 5 . We get this number thanks to the iterator, and, along with it, an indication that the generator is not completed yet (the done property in the object returned by the iterator is set to false ), that is, the function is only suspended.
The next time we call the iterator, we pass the number 7 to the generator.

 calc.next(7) 

In response, the iterator returns the following object.

 { done: false value: 14 } 

Here, the number 7 was used to calculate the doubleThat value.

At first glance it may seem that the input / 2 code is something like an argument of some function, but this is only the value returned in the first iteration. Here we skip this value and use the new input value 7 , multiplying it by 2 . After that we reach the second keyword yield , as a result, the value obtained at the second iteration is 14 .

At the next iteration, which is the last, we pass the number 100 to the generator.

 calc.next(100) 

In response, we get the following object.

 { done: true value: 14000 } 

The iteration is completed (the yield keyword no longer occurs in the generator), the object returns the result of evaluating the expression (input * doubleThat * another) , that is, 10 * 14 * 100 and indicating that the iterator is finished ( done: true ).

Let and const keywords


In JavaScript, the var keyword has always been used to declare variables. Such variables have a functional scope. The let and const keywords allow you to declare, respectively, variables and constants that have block scope.

This means that, for example, a variable declared with the let keyword in a loop, inside an if block, or inside a normal code block, delimited by curly brackets, will not be outside this block. Variables declared with var are not held in such blocks, becoming available in the function at the level of which they are declared.

The const keyword works in the same way as let , but with its help it declares constants that are immutable.

In modern JS code, the var keyword is rarely used. It has given way to the keywords let and const . At the same time, which may seem unusual, the key word const used quite widely today, which indicates the popularity of the ideas of the immutability of entities in modern programming.

Classes


It happened so that JavaScript was the only extremely widespread language using the prototype inheritance model. Programmers switching to JS from languages ​​that implement a class-based inheritance mechanism felt uncomfortable in such an environment. The ES2015 standard has introduced class support in JavaScript. This is, in fact, “syntactic sugar” around JS internal mechanisms using prototypes. However, this affects exactly how JS applications are written.

Now JavaScript's inheritance mechanisms look like similar mechanisms in other object-oriented languages.

 class Person { constructor(name) {   this.name = name } hello() {   return 'Hello, I am ' + this.name + '.' } } class Actor extends Person { hello() {   return super.hello() + ' I am an actor.' } } var tomCruise = new Actor('Tom Cruise') console.log(tomCruise.hello()) 

This program displays the text Hello, I am Tom Cruise. I am an actor to the console Hello, I am Tom Cruise. I am an actor Hello, I am Tom Cruise. I am an actor .
In JS classes, instance variables cannot be declared, they need to be initialized in constructors.

â–ŤConstructor class


Classes have a special method, constructor , which is called when creating an instance of a class using the new keyword.

SuperSword keyword super


The super keyword allows you to access the parent class from descendant classes.

â–ŤGetters and setters


The getter for a property can be set as follows.

 class Person { get fullName() {   return `${this.firstName} ${this.lastName}` } } 

The setter can be described as shown below.

 class Person { set age(years) {   this.theAge = years } } 

With getters and setters, they work as if they are not functions, but ordinary properties of objects.

Modules


Before the advent of the ES2015 standard, there were several competing approaches to working with modules. In particular, we are talking about the technologies RequireJS and CommonJS. This situation led to controversy in the community of JS-developers.

Nowadays, thanks to the standardization of modules in ES2015, the situation is gradually normalizing.

Import modules


Modules are imported using the import...from... construction. Here are some examples.

 import * as something from 'mymodule' import React from 'react' import { React, Component } from 'react' import React as MyLibrary from 'react' 

â–Ť Export of modules


The internal mechanisms of the module are closed from the outside world, but all that it can offer to other modules can be exported from the module. This is done using the export keyword.

 export var foo = 2 export function bar() { /* ... */ } 

â–ŤTemplate Literals


Sample literals are a new way to describe strings in JavaScript. Here's what it looks like.

 const aString = `A string` 

In addition, using the syntax of pattern literals allows you to embed expressions in strings, interpolate them. This is done using a ${a_variable} . Here is a simple example of its use:

 const v = 'test' const str = `something ${v}` //something test 

Here is an example more complicated, illustrating the possibility of calculating any expressions and substituting their results into a string.

 const str = `something ${1 + 2 + 3}` const str2 = `something ${foo() ? 'x' : 'y' }` 

Using template literals makes it much easier to declare multi-line strings.

 const str3 = `Hey this string is awesome!` 

Compare this with what you had to do to describe multi-line strings while using the features available in the language before ES2015.

 var str = 'One\n' + 'Two\n' + 'Three' 

Default Function Parameters


Functions now support default parameters — if the corresponding arguments are not passed to them when calling functions.

 const foo = function(index = 0, testing = true) { /* ... */ } foo() 

Spread operator


The spread operator (extension operator) allows you to "expand" arrays, objects or strings. This operator looks like three dots ( ... ). First, consider it on the example of an array.

 const a = [1, 2, 3] 

Here's how to create a new array based on this array.

 const b = [...a, 4, 5, 6] 

Here's how to create a copy of the array.

 const c = [...a] 

This operator works with objects. For example - here’s how to use it to clone an object.

 const newObj = { ...oldObj } 

By applying the spread operator to a string, you can convert it into an array, each element of which contains one character from this string.

 const hey = 'hey' const arrayized = [...hey] // ['h', 'e', 'y'] 

This operator, in addition to the above-described options for its use, is convenient to use when calling functions that expect a normal list of arguments, passing an array with these arguments to them.

 const f = (foo, bar) => {} const a = [1, 2] f(...a) 

Previously, this was done using a construct of the form f.apply(null, a) , but such code is more difficult to write and read worse.

Destructuring assignment


The destructive assignment technique allows, for example, to take an object, extract some values ​​from it, and place them in named variables or constants.

 const person = { firstName: 'Tom', lastName: 'Cruise', actor: true, age: 54, } const {firstName: name, age} = person 

Here the firstName and age properties are extracted from the object. The age property is written to the declared constant here with the same name, and the firstName property, after extraction, falls into the name constant.

Destructuring assignment is also suitable for working with arrays.

 const a = [1,2,3,4,5] const [first, second, , , fifth] = a 

In the first , second and fifth constants, the first, second, and fifth elements of the array, respectively, fall.

Empowering Object Literals


In ES2015, features for describing objects using object literals are greatly enhanced.

â–ŤSimplification of inclusion in variable objects


Previously, to assign any variable to the property of an object, you had to use the following construction.

 const something = 'y' const x = { something: something } 

Now the same can be done like this.

 const something = 'y' const x = { something } 

Prototypes


The object prototype can now be defined using the following construct.

 const anObject = { y: 'y' } const x = { __proto__: anObject } 

SuperSword keyword super


Using the super keyword, objects can access prototype objects. For example, to call their methods that have the same names as the methods of these objects themselves.

 const anObject = { y: 'y', test: () => 'zoo' } const x = { __proto__: anObject, test() {   return super.test() + 'x' } } x.test() //zoox 

â–ŤCalculated property names


Calculated property names are formed during the creation of an object.

 const x = { ['a' + '_' + 'b']: 'z' } x.a_b //z 

Cycle for ... of


In 2009, in the ES5 standard, forEach() cycles appeared. This is a useful design, the disadvantages of which include the fact that it is very inconvenient to interrupt such cycles. The classic for loop in situations where the execution of the loop needs to be interrupted before it ends normally, turns out to be a much more adequate choice.

In ES2015, a for...of loop appeared, which, on the one hand, is characterized by short syntax and convenience forEach , and on the other hand, it supports the possibilities for early exit from the loop.

Here are a couple of examples of a for...of loop.

 //    for (const v of ['a', 'b', 'c']) { console.log(v); } //           entries() for (const [i, v] of ['a', 'b', 'c'].entries()) { console.log(i, v); } 

Map and Set data structures


In ES2015, the Map and Set data structures appeared (as well as their “weak” WeakMap and WeakSet , the use of which makes it possible to improve the work of the “garbage collector” - the mechanism responsible for memory management in JS engines). These are very popular data structures, which, before their official implementation, had to be imitated by the available means of the language.

Results


Today we reviewed the capabilities of the ES2015 standard, which have greatly influenced the current state of the language. Our next topic will be the features of ES2016, ES2017 and ES2018 standards.

Dear readers! What innovations of the ES6 standard seem to you the most useful?

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


All Articles