- PVSM.RU - https://www.pvsm.ru -
Шаблонные литералы заключены в обратные кавычки (` `) вместо двойных или одинарных. Они могут содержать подстановки, обозначаемые знаком доллара и фигурными скобками (${выражение}).
Пример:
var name = "bill";
console.log(`Hello ${name}`); // Hello bill
Областью видимости переменных, объявленных ключевым словом let и const, является блок, в котором они объявлены, и все его подблоки. В этом работа директива let схожа с работой директивы var. Основная разница заключается в том, что областью видимости переменной, объявленной директивой var, является вся функция, в которой она объявлена. К тому же переменные объявленные с ключевым словом const являются неизменными константами. При декларации переменной с ключевым словом const необходимо использовать оператор присваивания для задания значения константе.
Пример отличия глобальной и блочной области видимости:
function myFunction() {
if (true)
let a = 5;
console.log(a); //SyntaxError так как a доступна только в блоке if
if (true)
var b = 5;
console.log(b); //5 так как b доступна во всей функции
}
Выражения стрелочных функций имеют более короткий синтаксис по сравнению с функциональными выражениями и лексически привязаны к значению this (но не привязаны к собственному this, arguments, super, или new.target). Стрелочные функции всегда анонимные.
Примеры стрелочных функции:
const sum = (a, b) => a + b;
const squared = a => a*2;
const myFun = () => someFun();
const Fun = (data) => { data.response }
Оператор for...of выполняет цикл обхода итерируемых объектов (включая Array, Map, Set, объект аргументов и подобных), вызывая на каждом шаге итерации операторы для каждого значения из различных свойств объекта.
Почему НЕ СЛЕДУЕТ использовать for...in цикл для итерации? Потому что в зависимости от движка, JavaScript может итерировать в произвольном порядке, что может привести к непредсказуемому результату. Кроме того, итерационная переменная представляет собой строку, а не число, а значит, если вы собираетесь производить какие — либо подсчеты с переменной, вам потребуется провести конкатенацию строк вместо добавления. Так что во избежание логических ошибок не следует его использовать!
Синтаксис цикла for...of
for (var i of arr) //for (переменная of объект)
arr[i] = "something value"
Синтаксис объявления объектов и их элементов поддерживает вычисляемые имена свойств. Это позволяет добавлять в скобки [] выражение, которое будет вычислено, как имя свойства. Оно напоминает шаблонные литералы.
Пример вычисляемых имён:
var a = () => "world";
var a = {
["a" + (10 - 6)]: {
["some" + "string"]: true,
[10 + 20]: 10,
[`hello ${a()}`]: a()
}
}
Метод Object.assign() используется для копирования значений всех собственных перечисляемых свойств из одного или более исходных объектов в целевой объект. После копирования он возвращает целевой объект.
Пример использования Object.assign():
var = newStudent = Object.assign({}, person, student);
Теперь newStudent содержит все свойства и методы person и student.
В ES5 при созданий дубликата объекта происходит эффект мутаций, когда изменения дубликата отражаются на родительском объекте.
var A = { a: 1 };
var B = A;
B.a = 2;
Казалось бы мы изменяем свойство объекта B НО после выполнения данного кода и B.a и A.a будут равны 2. Ситуацию можно исправить используя метод Object.assign().
var A = { a: 1 };
var B = Object.assign({}, A);
B.a = 2;
Теперь только B.a будет равно 2 а, A.a всё также равно 1.
В Object.assign() можно сразу задать значения свойства и декларировать новые передав их как аргумент.
var A = { a: 1 };
var B = Object.assign({ b: 3}, A, { a: 2 });
Создаётся свойство b и изменяем значение свойства а из родительского объекта.
И теперь B.a равно 2. B.b равно 3.
Синтаксис оставшихся параметров функции позволяет представлять неограниченное множество аргументов в виде массива. Если последний именованный аргумент функции имеет префикс ..., то он автоматически становится массивом с элементами от 0 до theArgs.length в соответствии с актуальным количеством аргументов, переданных в функцию.
Пример использования синтаксиса оставшихся параметров:
function name (a, b, ...c) {}
name (0, 1, 2, 3,)
В этом примере a = 0 b = 1 c[0] = 2 c[1] = 3
Если оставшийся параметр не передан то он будет пустым массивом (в отличии от обычных параметров он никогда не будет undefined).
Данный синтаксис можно использовать не только в аргументах функции но и в других местах, например для копирования и объединения массивов:
var a = [ 0, 1, 2 ];
var b = [ 3, 4, 5 ];
var c = [ ...a, ...b ]; // [ 0, 1, 2, 3, 4, 5 ]
Теперь можно определять значения по умолчанию (отличное от undefined) параметрам которые не были переданы в функцию.
Пример использования параметров по умолчанию:
function myFun(a=5) {
return a*a;
}
console.log(myFun()); // 25
Синтаксис деструктурирующего присваивания в выражениях JavaScript позволяет извлекать данные из массивов или объектов при помощи синтаксиса, подобного объявлению массива или литералов в объекте.
Пример деструктурирующего присваивания:
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
Map — Объект содержащий пары ключ-значение и сохраняющий порядок вставки. Любое значение (как объекты, так и примитивы) могут быть использованы в качестве ключей.
Пример:
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 () {}
Отличие Map от Object:
Свойства и методы:
Set — Позволяет сохранять уникальные значения любого типа, как примитивы, так и другие типы объектов. Объекты Set представляют коллекции значений, по которым можно выполнить обход в порядке вставки элементов. Значение элемента в Set может присутствовать только в одном экземпляре, что обеспечивает его уникальность в коллекции Set. Во всём остальном не отличается от Map.
class Student {
constructor(name) {
this.name = name;
}
}
var robert = new Student('Robert');
console.log(robert.name); // Outputs 'Robert'
При созданий новых объектов от класса будет запускаться constructor(), который необходим для инициализации объектов.
class Student {
constructor(name) {
this.name = name;
}
sayName() {
return "Hi my name is " + this.name;
}
static stMethod () {
// do something
}
}
var robert = new Student('Robert');
Student.stMethod(); // Статические методы можно вызвать только из класса а, не из объектов образованных от класса
console.log(robert.sayName()); // "Hi my name is Robert"
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);
В ES6 нет встроенной инкапсуляций, но ее можно организовать самому. Например вот так:
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
С помощью ключевого слова extends можно наследовать своиства и методы другого класса.
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
Promise это новый способ делать асинхронные вычисления без состояния гонки.
Promise может находиться в трёх состояниях:
Создание обещаний (promise) выполняется следующим образом:
const myPromise = new Promise((resolve, reject) => {
resolve(someValue); // успешное завершение
reject("failure reason"); // неудача
});
Объект функции с двумя аргументами resolve и reject вызывает успешное выполнение обещания, второй отклоняет его.
Чтобы снабдить функцию функционалом обещаний, нужно просто вернуть в ней объект Promise.
С помощью .then прикрепляются обработчики выполнения и отклонения обещания.
В этом примере создаётся асинхронный http запрос:
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 // Если не забыли передать url :D
{
resolve(() => {
fetch(url).then((response) => { // Создаём запрос
return response.json(); // Извлекаем содержимое тела JSON из ответа
}).then((myJson) => {
return(console.log(myJson)); // Выводим результат запроса в консоль
});
});
}
}
);}
asyncHttpRequest(URL).then((result) => result(), (error) => console.log(error));
Iterable — Это объект, содержание которого можно перебрать.
Итерируемый объект отличается от не итерируемого тем что имеет специальный метод который возвращает объект, для доступа к которому используется специальный символ: Symbol.iterator
Iterable {
[Symbol.iterator]()
}
Обьект возврощяющий этод метод формально называется итератор.
У итератора есть всего лишь один метод next()
Iterator {
next();
}
Который возврощяет обьект (назавём его itreratorResult) c двумя своиствами done и value
IteratorResult {
done,
value
}
done указывает есть ли еще значение в перебираемой последовательности а value содержит следующий элемент последовательности.
Для перебора итерируемых объектов был добавлен цикл for...of. Зачем же тогда нужен итератор? Если честно… я не знаю. Итератор это служебный метод, и вам врятле придется иметь с ним дело. Но понимание того что он из себя представляет нужно.
Собственно так выглядит сам итератор:
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
}
}
Генераторы — это специальный тип функции, который работает как фабрика итераторов. Функция становится генератором, если содержит один или более yield операторов и использует function* синтаксис.
А если говорить проще то генераторы это новый вид функций которые могут приостанавливать свое выполнение и возвращать промежуточный результат и возобновлять выполнение позже.
Давайте рассмотрим обычную функцию выполняющую некоторые математические вычисления и возвращающую результат:
function myFunction (a) {
a = a*2;
a = a - 1;
return a;
}
console.log(myFunction(5)); // 9
Теперь взгляните на аналогичную функцию генератор:
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
Как говорилось раньше генераторы могут приостанавливать своё выполнение и возвращать промежуточный результат. Из этого примера видно что на момент первого вызова функция как бы приостанавливает свое выполнение на первом брекпоинте yield и возвращает результат первого выражения. Во втором вызове функция продолжает с предыдущего брекпоинта и двигается к следующему, возвращая результат уже следующего выражения.
Функции генераторы предоставляют мощный инструмент для написания сложных последовательных функций.
Symbol — это уникальный и неизменяемый тип данных, который может быть использован как идентификатор для свойств объектов. Они являются служебными инструментами и поэтому вам вряд ли придётся с ними работать, но знать их нужно. Зачем же нужен новый тип данных? Он нужен для того что бы разработчики языка могли добавлять новые идентификаторы или свойства объектов при этом не резервируя строковые названия для этих свойств.
Так вы можете создать символьное свойство:
var user = {
name: "Alex",
[Symbol("password")]: "12hsK3I"
}
Для получения массива символьных объектов используйте свойство Object.getOwnPropertySymbols(obj);
Для получения доступа в любом месте вашего кода используйте методы Symbol.for() и Symbol.keyFor()
Автор: Elliot_001
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/324535
Ссылки в тексте:
[1] Источник: https://habr.com/ru/post/460741/?utm_campaign=460741&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.