Зачем нужны классы? Давайте представим, что нам нужно создать индивидуальные профили для 50 собак. Для этого нам нужно хранить данные (локально) для каждой собаки в отдельных объектах, содержащих такие свойства, как имя, порода, вес, скорость и т. д. Каждый объект будет содержать один и тот же набор свойств с разными значениями. Для этого мы могли бы создать класс с этими свойствами.

Что такое классы? Проще говоря, классы — это функции для создания экземпляров объектов. Эти объекты содержат свойства и методы, унаследованные от их прототипа. Прототип определен в функции класса.

Как работают классы? Сначала вы определяете функцию класса. Стандартное соглашение об именах для классов состоит в том, чтобы первая буква была в верхнем регистре. Во-вторых, вы определяете свойства и методы, которые будут включены в прототип. Для определения свойств вы будете использовать функцию-конструктор. Функция-конструктор принимает параметры/аргументы, которые можно использовать для установки значений динамических свойств. Чтобы определить методы, просто определите их непосредственно в самой функции класса (не в функции-конструкторе). Наконец, чтобы создать новый экземпляр желаемого объекта, используйте ключевое слово «new» для вызова функции класса, передавая аргументы, которые будут переданы в функцию-конструктор. Теперь, используя запись через точку или скобки, вы можете вызывать любые методы или свойства, которые были унаследованы от прототипа.

class Dog {
  constructor(name, weight) {
    /* When the instance of the Dog is created using the "new"
  keyword, "this" is bound to the newly-created object */
    this.name = name;
    this.weight = weight;
  }
  /* Adding a method to the prototype. */
  speak() {
    return `${this.name} says woof.`;
  }
}
const dog = new Dog('Spot', 20);
console.log(dog); // Dog { name: 'Spot', weight: 20 }
console.log(dog.name); // Spot
console.log(dog.speak()); // Spot says woof.

Как расширить класс? Представим, что я хочу определить класс Greyhound, похожий на класс Dog. Я хочу скопировать свойства и методы, которые я определил в классе Dog. Для этого я могу использовать ключевое слово «extend». В этом случае класс Dog становится родительским, а класс Greyhound — дочерним. Чтобы получить доступ к функции-конструктору в родительском классе (Dog), я могу использовать ключевое слово «super» в дочернем классе (Greyhound). Я также могу добавить дополнительные свойства в функцию-конструктор дочернего класса или добавить дополнительные методы непосредственно в функцию класса Greyhound. Опять же, я вызову функцию класса Greyhound, используя ключевое слово «new», и передам аргументы, которые будут переданы в функцию-конструктор. В приведенном ниже примере я добавил свойство скорости и метод run() к прототипу Greyhound.

class Greyhound extends Dog {
  constructor(name, weight, speed) {
    /* call the parent constructor (Dog) with the name and weight arguments */
    super(name, weight);
    // Add a new property
    this.speed = speed;
  }
  run() {
    return `${this.name}'s speed is ${this.speed}`;
  }
}
const greyhound = new Greyhound('Alex', 20, 40);
console.log(greyhound); //Greyhound { name: 'Alex', weight: 20, speed: 40 }
console.log(greyhound.speak()); //Alex says woof.
console.log(greyhound.run()); //Alex's speed is 40

Что такое это на занятиях? При вызове функции класса Greyhound значение this указывает на вновь созданный экземпляр Greyhound (верхний регистр), который является greyhound (нижний регистр). В функции-конструкторе мы устанавливаем this.speed = скорость. Поэтому функция конструктора устанавливает greyhound.speed = скорость.