Мастер Полный ES6

Объявления блочной области (let и const)
В ES6 появились ключевые слова let и const для объявления переменных. Эти объявления имеют блочную область видимости, то есть они существуют только внутри блока, в котором они объявлены, в отличие от var, область действия которой — функция.

function foo() {
  let x = 10; // x is block-scoped to foo
  const y = 20; // y is also block-scoped to foo
  
  if (true) {
    let x = 30; // this is a new block-scoped x, shadowing the previous one
    const y = 40; // this is a new block-scoped y, shadowing the previous one
    console.log(x, y); // output: 30, 40
  }
  
  console.log(x, y); // output: 10, 20
}

foo();

В этом примере ключевые слова let и const используются для объявления блочных переменных x и y. Первое объявление x и y находится в области видимости функции foo, поэтому они доступны во всей функции. Второе объявление x и y находится в пределах блока оператора if, поэтому они доступны только внутри этого блока.

Когда оператор console.log() выполняется внутри блока if, он выводит значения второго объявления x и y. Когда операторы console.log() выполняются вне блока if, они выводят значения первого объявления x и y.

Стоит отметить, что использование let или const для объявления переменной с тем же именем, что и у переменной, объявленной во внешней области видимости, создает новую переменную с тем же именем во внутреннем блоке, затеняющую внешнюю переменную. Вот почему второй оператор console.log() выводит значение первого объявления y, а не второго.

Стрелочные функции
Стрелочные функции обеспечивают более краткий синтаксис для написания функций. У них также есть лексическая привязка, то есть они наследуют это значение из окружающего кода.

Пример 1: Базовый синтаксис стрелочной функции

// A function that adds two numbers using arrow function syntax
const add = (a, b) => a + b;
console.log(add(2, 3)); // output: 5

Пример 2: Стрелочные функции с одним параметром

// A function that doubles a number using arrow function syntax
const double = x => x * 2;
console.log(double(3)); // output: 6

Пример 3: Стрелочные функции без параметров

// A function that returns a random number between 0 and 1 using arrow function syntax
const getRandomNumber = () => Math.random();
console.log(getRandomNumber()); // output: a random number between 0 and 1

Пример 4. Стрелочные функции с несколькими операторами

// A function that checks if a number is even using arrow function syntax
const isEven = x => {
  if (x % 2 === 0) {
    return true;
  } else {
    return false;
  }
}
console.log(isEven(4)); // output: true

Пример 5: Стрелочные функции с ключевым словом this

// An object with a method that uses the this keyword
const person = {
  name: 'John',
  sayHi: function() {
    console.log('Hi, my name is ' + this.name);
  }
}
person.sayHi(); // output: Hi, my name is John

// The same object with a method that uses an arrow function
const person2 = {
  name: 'Jane',
  sayHi: () => {
    console.log('Hi, my name is ' + this.name);
  }
}
person2.sayHi(); // output: Hi, my name is undefined

В этом примере метод sayHi() функции person2 использует функцию стрелки, что означает, что this относится к глобальному объекту, а не к объекту, методом которого является функция. В результате выводится Hi, my name is undefined. Это одно из различий между стрелочными функциями и обычными функциями, которые имеют собственную привязку this.

Литералы шаблонов
Литералы шаблонов позволяют включать переменные и выражения в строки. Они используют обратные кавычки (`) вместо кавычек и допускают многострочные строки.

Пример 1. Синтаксис литерала базового шаблона

// A string with interpolated variables using template literal syntax
const name = 'John';
console.log(`Hello, ${name}!`); // output: Hello, John!

Пример 2. Литералы шаблонов с выражениями

// A string with an expression using template literal syntax
const x = 5;
const y = 10;
console.log(`The sum of ${x} and ${y} is ${x + y}.`); // output: The sum of 5 and 10 is 15.

Пример 3. Многострочные строки с использованием литералов шаблонов

// A multiline string using template literal syntax
const message = `This is a
multiline string
using template
literal syntax.`;
console.log(message); // output: This is a
                     //         multiline string
                     //         using template
                     //         literal syntax.

Пример 4: Литералы шаблонов с вызовами функций

// A function that returns a string using template literal syntax
function greet(name) {
  return `Hello, ${name}!`;
}
console.log(greet('John')); // output: Hello, John!

Пример 5: Литералы шаблонов с тегами

// A tagged template literal that formats a string using a custom function
function formatString(strings, ...values) {
  let result = '';
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < values.length) {
      result += values[i];
    }
  }
  return result;
}

const x = 5;
const y = 10;
console.log(formatString`The sum of ${x} and ${y} is ${x + y}.`); // output: The sum of 5 and 10 is 15.

В этом примере функция formatString() представляет собой помеченный литерал шаблона, который принимает в качестве аргументов массив строк и разброс значений. Затем он объединяет строки и значения особым образом, чтобы получить окончательную отформатированную строку. Литерал шаблона передается в качестве первого аргумента функции, а значения передаются в качестве дополнительных аргументов с использованием синтаксиса распространения.

Присваивание деструктурирования
Присваивание деструктурирования позволяет извлекать значения из массивов или объектов и назначать их переменным более кратким способом.

Пример 1: Разрушение массива

const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;

console.log(first); // output: 1
console.log(second); // output: 2
console.log(rest); // output: [3, 4, 5]

В приведенном выше коде мы объявляем массив numbers с некоторыми значениями. Затем мы используем деструктурирующее присваивание, чтобы присвоить первый и второй элементы массива переменным first и second соответственно. Мы также используем параметр rest (...rest), чтобы присвоить оставшиеся элементы массива переменной rest.

Пример 2: Разрушение объекта

const person = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30,
  city: 'New York'
};

const { firstName, lastName, age } = person;

console.log(firstName); // output: John
console.log(lastName); // output: Doe
console.log(age); // output: 30

В приведенном выше коде мы объявляем объект person с некоторыми свойствами. Затем мы используем деструктурирующее присваивание, чтобы присвоить свойства firstName, lastName и age объекта переменным с тем же именем.

Параметры функции по умолчанию
ES6 позволяет использовать параметры функции по умолчанию, которые используются, когда в функцию не передается аргумент.

function greet(name = 'Guest') {
  console.log(`Hello, ${name}!`);
}

greet(); // output: Hello, Guest!
greet('John'); // output: Hello, John!

В приведенном выше коде мы определяем функцию greet, которая принимает параметр name. Мы предоставляем значение по умолчанию 'Guest' для параметра name. Если параметр name не указан при вызове функции, будет использоваться значение по умолчанию.

Rest-параметры
Rest-параметры позволяют передавать неопределенное количество аргументов функции в виде массива.

function sum(...numbers) {
  let result = 0;
  for (let i = 0; i < numbers.length; i++) {
    result += numbers[i];
  }
  return result;
}

console.log(sum(1, 2, 3)); // output: 6
console.log(sum(4, 5, 6, 7)); // output: 22

В приведенном выше коде мы определяем функцию sum, которая принимает остаточный параметр ...numbers. Параметр rest позволяет нам представить неопределенное количество аргументов в виде массива. Внутри функции мы перебираем массив numbers и складываем все значения, чтобы получить общую сумму.

Оператор спреда
Оператор спреда в JavaScript обозначается тремя точками .... Он позволяет распределять элементы итерируемого объекта (например, массива или объекта) на отдельные элементы или свойства.

Например, предположим, что у вас есть массив чисел. Если вы хотите передать эти числа как отдельные аргументы функции, вы можете использовать оператор распространения, чтобы «распределить» элементы массива по отдельным аргументам:

const numbers = [1, 2, 3];

function sum(a, b, c) {
  return a + b + c;
}

console.log(sum(...numbers)); // Output: 6

В приведенном выше коде мы используем оператор распространения для передачи массива numbers в качестве отдельных аргументов функции sum. Оператор расширения «распределяет» элементы массива numbers по отдельным аргументам a, b и c, чтобы функция могла вычислить их сумму.

Классы и наследование
В ES6 появился синтаксис класса для создания объектов и наследования с использованием ключевого слова extends. Классы — это способ создания объектов, которые имеют схожие свойства и методы. Они предоставляют схему создания новых объектов, которые можно повторно использовать и расширять.

Вот пример того, как определить класс в JavaScript:

class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  sayName() {
    console.log(`My name is ${this.name}`);
  }
  
  sayAge() {
    console.log(`I am ${this.age} years old`);
  }
}

В приведенном выше коде мы определяем класс Animal, который имеет метод constructor и два дополнительных метода sayName и sayAge. Метод constructor вызывается при создании нового экземпляра класса и используется для установки начальных свойств объекта.

Мы можем создать новый экземпляр класса Animal, используя ключевое слово new и передав необходимые аргументы методу constructor:

const dog = new Animal('Spot', 3);
dog.sayName(); // Output: "My name is Spot"
dog.sayAge(); // Output: "I am 3 years old"

Наследование — это способ создания нового класса, являющегося модифицированной версией существующего класса. Это позволяет вам повторно использовать свойства и методы родительского класса и добавлять или переопределять их по мере необходимости.

Вот пример того, как определить дочерний класс, который наследуется от родительского класса в JavaScript:

class Dog extends Animal {
  constructor(name, age, breed) {
    super(name, age);
    this.breed = breed;
  }
  
  bark() {
    console.log('Woof!');
  }
  
  sayBreed() {
    console.log(`I am a ${this.breed}`);
  }
}

В приведенном выше коде мы определяем класс Dog, который расширяет класс Animal, используя ключевое слово extends. Мы также определяем метод constructor, который вызывает метод super для передачи необходимых аргументов родительскому классу и устанавливает дополнительное свойство breed для объекта.

Мы можем создать новый экземпляр класса Dog так же, как и раньше:

const myDog = new Dog('Fido', 2, 'Labrador');
myDog.sayName(); // Output: "My name is Fido"
myDog.sayAge(); // Output: "I am 2 years old"
myDog.sayBreed(); // Output: "I am a Labrador"
myDog.bark(); // Output: "Woof!"

Промисы
Промисы позволяют обрабатывать асинхронные операции и избегать ада обратных вызовов. У них есть три состояния: ожидание, выполнено и отклонено.

Вот пример использования промисов в JavaScript:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const randomNum = Math.random();
    if (randomNum > 0.5) {
      resolve(randomNum);
    } else {
      reject(new Error('Random number is less than 0.5'));
    }
  }, 1000);
});

promise.then(result => {
  console.log(`Promise resolved with result: ${result}`);
}).catch(error => {
  console.error(`Promise rejected with error: ${error}`);
});

Здесь мы создаем новое обещание, которое имитирует асинхронную операцию с использованием setTimeout. Если сгенерированное случайное число больше 0,5, обещание разрешается с этим значением. В противном случае он отклоняется с ошибкой.

Затем мы используем методы then и catch для обработки результата промиса. Метод then вызывается, если обещание успешно разрешено, и метод catch вызывается, если обещание отклонено.

Модули
Модули ES6 позволяют организовать код в отдельные файлы, а также экспортировать и импортировать функции между ними.

Вот пример того, как экспортировать модуль:

// module.js
export function greet(name) {
  console.log(`Hello, ${name}!`);
}

Здесь мы определяем модуль, который экспортирует одну функцию greet. Эта функция записывает приветствие на консоль с заданным именем.

Затем мы можем импортировать этот модуль и использовать функцию greet в другом файле:

// app.js
import { greet } from './module.js';

greet('John'); // Output: "Hello, John!"

Это некоторые из основных функций, представленных в ES6. Используя эти функции, вы можете писать более лаконичный и читаемый код.

Если вы дочитали до сих пор, сделайте себе комплимент, так как не все читают от начала до конца, но вы это сделали, и у вас есть возможность оставаться впереди в жизни.