Pattern Literals
Sample literals are enclosed in backquotes (``) instead of double or single. They may contain substitutions, denoted by a dollar sign and curly brackets ($ {expression}).
Example:
var name = "bill"; console.log(`Hello ${name}`);
Directives let const
The scope of variables declared by the let and const keywords is the block in which they are declared, and all its sub-blocks. In this work, the let directive is similar to the var directive. The main difference is that the scope of the variable declared by the var directive is the entire function in which it is declared. In addition, variables declared with the const keyword are constant constants. When declaring a variable with the const keyword, you must use an assignment operator to set a constant value.
')
An example of the difference between the global and block scope:
function myFunction() { if (true) let a = 5; console.log(a);
Arrow functions
The expressions of the switch functions have a shorter syntax compared to functional expressions and are lexically bound to the value of this (but not attached to its own this, arguments, super, or new.target). Arrow functions are always anonymous.
Examples of arrow functions: const sum = (a, b) => a + b; const squared = a => a*2; const myFun = () => someFun(); const Fun = (data) => { data.response }
For ... of
The for ... of operator performs a loop traversal of iterated objects (including Array, Map, Set, an object of arguments and the like), calling at each iteration step operators for each value from the various properties of the object.
Why SHOULD NOT use a for ... in loop to iterate? Because, depending on the engine, JavaScript can iterate in random order, which can lead to unpredictable results. In addition, the iteration variable is a string, not a number, which means that if you are going to perform any calculations with a variable, you will need to concatenate the strings instead of adding them. So in order to avoid logical errors should not use it!
For ... of loop for (var i of arr)
Calculated Names
The syntax for declaring objects and their elements supports computed property names. This allows brackets [] to add an expression that will be evaluated as the name of a property. It resembles patterned literals.
Example of calculated names: var a = () => "world"; var a = { ["a" + (10 - 6)]: { ["some" + "string"]: true, [10 + 20]: 10, [`hello ${a()}`]: a() } }
Object.assign ()
The Object.assign () method is used to copy the values ββof all of its own enumerated properties from one or more source objects to the target object. After copying, it returns the target object.
An example of using Object.assign ():
var = newStudent = Object.assign({}, person, student);
Now newStudent contains all the properties and methods of the person and the student.
In ES5, when creating a duplicate object, a mutation effect occurs when changes in the duplicate are reflected on the parent object.
var A = { a: 1 }; var B = A; Ba = 2;
It would seem that we change the property of object B BUT after executing this code, and Ba and Aa will be equal to 2. The situation can be corrected using the Object.assign () method.
var A = { a: 1 }; var B = Object.assign({}, A); Ba = 2;
Now only Ba will be equal to 2 a, Aa still equal to 1.
In Object.assign (), you can immediately set the property values ββand declare new ones by passing them as an argument.
var A = { a: 1 }; var B = Object.assign({ b: 3}, A, { a: 2 });
Property b is created and the value of property a is changed from the parent object.
And now Ba is 2. Bb is 3.
Remaining parameters
The syntax of the remaining parameters of the function allows you to represent an unlimited set of arguments in the form of an array. If the last named argument of the function has a prefix ..., then it automatically becomes an array with elements from 0 to theArgs.length in accordance with the actual number of arguments passed to the function.
An example of using the syntax of the remaining parameters:
function name (a, b, ...c) {} name (0, 1, 2, 3,)
In this example, a = 0 b = 1 c [0] = 2 c [1] = 3
If the remaining parameter is not passed, it will be an empty array (unlike normal parameters, it will never be undefined).
This syntax can be used not only in function arguments but also in other places, for example, to copy and merge arrays:
var a = [ 0, 1, 2 ]; var b = [ 3, 4, 5 ]; var c = [ ...a, ...b ];
Default settings
Now you can define default values ββ(other than undefined) to parameters that were not passed to the function.
An example of using default parameters:
function myFun(a=5) { return a*a; } console.log(myFun());
Destructuring assignment
The syntax for destructive assignment in JavaScript expressions allows you to extract data from arrays or objects using a syntax similar to declaring an array or literals in an object.
Example of destructive assignment:
var a, b, rest; [a, b] = [1, 2]; console.log(a);
Map and Set
Map - An object containing key-value pairs and preserving the insertion order. Any value (both objects and primitives) can be used as keys.
Example:
var myMap = new Map(); var keyObj = {}, keyFunc = function () {}, keyString = "a string";
Difference Map from Object:
- Object keys are Strings and Characters, while any value can be a Map key, including functions, objects, and primitives.
- Unlike Objects, the keys in the Map are ordered. Thus, during Map iteration, the keys are returned in the order of insertion.
- You can easily get the number of elements in the Map using the size property, while the number of Object elements can only be determined manually.
- Map is an iterable object and can be iterated directly, while the Object requires manual retrieval of a list of keys and their iteration.
- The object has a prototype and therefore has a standard set of keys that, if careless, may intersect with your keys. Since the release of ES5, this can be changed with map = Object.create (null).
- Map may have better performance in cases of frequent addition or deletion of keys.
Properties and methods:
- Map.prototype.size - Returns the number of key / value pairs on a Map.
- Map.prototype.set (key, value) - Adds the transferred key / value pair to the Map. If the specified key already exists, it will be overwritten by the new value.
- Map.prototype.get (key) - Returns the value of the passed key. If there is no key, then undefined
- Map.prototype.has (key) - Returns true if the transferred key exists and false if it does not exist.
- Map.prototype.delete (key) - Deletes the specified key / value pair and returns true. Returns false if the key does not exist.
- Map.prototype.clear () - Removes all key / value pairs from the Map.
- Map.prototype.keys () - Returns an iterator of keys on the Map for each item.
- Map.prototype.values ββ() - Returns an iterator of the values ββin Map for each item.
- Map.prototype.entries () - Returns an iterator of the [key, value] array on the Map for each element.
Set - Allows you to save unique values ββof any type, both primitives and other types of objects. Set objects represent collections of values ββthat can be traversed in order to insert items. The value of an element in a Set can be present only in one instance, which ensures its uniqueness in the Set collection. For the rest, no different from Map.
Classes
Constructors
class Student { constructor(name) { this.name = name; } } var robert = new Student('Robert'); console.log(robert.name);
When creating new objects from a class, constructor () will be launched, which is necessary for initializing objects.
Methods
class Student { constructor(name) { this.name = name; } sayName() { return "Hi my name is " + this.name; } static stMethod () {
Getters and Setters
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;
- setter - Required for validations of written parameters (as in the example above)
- getter - Required for getting properties (although you can get them directly). Cannot have arguments
In ES6, there is no built-in encapsulation, but you can organize it yourself. For example, like this:
var Student = (function () { let privateProps = new WeakMap(); class Person { constructor(name, Age) { this.name = name;
Inheritance
Using the extends keyword, you can inherit the properties and methods of another class.
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());
- In the child class, you need to call super () before using this to call the parent class constructor.
- super () can be used to call methods of the parent class from a child.
Promise
Promise is a new way to do asynchronous computing without a race condition.
Promise can be in three states:
- pending: initial state, not met and not rejected.
- fulfilled: the operation completed successfully.
- rejected: operation completed with an error.
Creating promises is done as follows:
const myPromise = new Promise((resolve, reject) => { resolve(someValue);
The function object with two arguments, resolve and reject, causes the promise to succeed, the second one rejects it.
To provide the function with promises functionality, you just need to return the Promise object in it.
Handler execution and reject promises are attached using .then.
This example creates an asynchronous http request:
const URL = "https://getfestivo.com/v1/holidays?api_key=f8f42551-eb66-49d2-bcba-b8e42727ddfb&country=US&year=2019";
Iterators
Iterable - This is an object whose contents can be iterated.
An iterable object differs from a non-iterable one in that it has a special method that returns an object for which the special symbol is used: Symbol.iterator
Iterable { [Symbol.iterator]() }
The object returning this method is formally called an iterator.
The iterator has only one method next ()
Iterator { next(); }
Which returns an object (let's name it itreratorResult) with two properties done and value
IteratorResult { done, value }
done indicates whether there is another value in the sequence being searched, and value contains the next element of the sequence.
A loop for ... of has been added to iterate through the objects being iterated. Why, then, need an iterator? To be honest ... I do not know. The iterator is a utility method, and you will have to deal with it vryatle. But the understanding of what he is is necessary.
Actually, the iterator itself looks like this:
function makeIterator(array){ var nextIndex = 0; return { next: function(){ return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {done: true}; } } }
Generators
Generators are a special type of function that works as an iterator factory. A function becomes a generator if it contains one or more yield operators and uses the function * syntax.
And if it is easier to say, then generators are a new kind of functions that can suspend their execution and return an intermediate result and resume execution later.
Let's look at a normal function that performs some mathematical calculations and returns a result:
function myFunction (a) { a = a*2; a = a - 1; return a; } console.log(myFunction(5));
Now take a look at a similar function generator:
function* generator(a) { a = a*2; yield a; a = a - 1; yield a; } var it = generator(5); console.log(it.next().value);
As mentioned earlier, generators can suspend their execution and return an intermediate result. This example shows that at the time of the first call, the function seems to suspend its execution at the first yield point and returns the result of the first expression. In the second call, the function continues from the previous blockpoint and moves to the next, returning the result of the next expression.
Functions generators provide a powerful tool for writing complex sequential functions.
Symbol
Symbol is a unique and immutable data type that can be used as an identifier for object properties. They are service tools and therefore you hardly have to work with them, but you need to know them. Why do we need a new data type? It is needed so that language developers can add new identifiers or properties of objects without reserving string names for these properties.
So you can create a character property:
var user = { name: "Alex", [Symbol("password")]: "12hsK3I" }
To get an array of character objects, use the Object.getOwnPropertySymbols (obj) property;
To gain access anywhere in your code, use the Symbol.for () and Symbol.keyFor () methods.