Конструкторы и классы

Free Preview
Продолжительность: 12 мин

В уроке про типы данных мы видели, что объекты позволяют группировать связанные данные. Но что если нужно создавать много похожих объектов одного «вида» — например, сотни карточек товаров или пользователей? Создавать каждый вручную неудобно. Для этого в JavaScript существуют конструкторы и классы.

Конструктор-функция

Исторически для создания объектов одного вида использовались конструктор-функции. По соглашению их называют с заглавной буквы:

function City(name, foundedYear) {
  this.name = name;
  this.foundedYear = foundedYear;
  this.getAge = function() {
    return new Date().getFullYear() - this.foundedYear;
  };
}

const spb = new City('Санкт-Петербург', 1703);
const msk = new City('Москва', 1147);

console.log(spb.name);      // Санкт-Петербург
console.log(msk.getAge());  // примерно 877
js

Ключевое слово new при вызове функции делает несколько вещей автоматически: создаёт новый пустой объект, передаёт его как this внутрь функции, и возвращает этот объект в конце.

Классы

В современном JavaScript есть более удобный синтаксис для той же задачи — классы. По сути, это «синтаксический сахар» поверх конструктор-функций: под капотом работает та же механика, просто записывается чище:

class City {
  constructor(name, foundedYear) {
    this.name = name;
    this.foundedYear = foundedYear;
  }

  getAge() {
    return new Date().getFullYear() - this.foundedYear;
  }

  describe() {
    console.log(`${this.name} основан в ${this.foundedYear} году.`);
  }
}

const spb = new City('Санкт-Петербург', 1703);
spb.describe(); // Санкт-Петербург основан в 1703 году.
js

Метод constructor вызывается автоматически при создании объекта через new. Остальные методы описываются внутри тела класса.

Наследование

Классы поддерживают наследование — один класс может расширять другой, получая его свойства и методы:

class Settlement {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Добро пожаловать в ${this.name}!`);
  }
}

class City extends Settlement {
  constructor(name, foundedYear) {
    super(name); // вызываем конструктор родителя
    this.foundedYear = foundedYear;
  }

  getAge() {
    return new Date().getFullYear() - this.foundedYear;
  }
}

const spb = new City('Санкт-Петербург', 1703);
spb.greet();   // Добро пожаловать в Санкт-Петербург! — метод из родителя
spb.getAge();  // метод из City
js

extends указывает, от какого класса наследоваться. super() внутри конструктора вызывает конструктор родительского класса — это обязательно, если дочерний класс объявляет constructor.

Статические методы и свойства

Иногда нужны методы, которые относятся к самому классу, а не к конкретному экземпляру. Для этого используется ключевое слово static:

class City {
  constructor(name) {
    this.name = name;
  }

  static create(name) {
    return new City(name);
  }
}

const spb = City.create('Санкт-Петербург'); // вызов через класс, не через экземпляр
console.log(spb.name); // Санкт-Петербург
js

Статические методы вызываются через имя класса, а не через созданный объект.

Важно понимать

Классы в JavaScript — это не то же самое, что классы в Java или C#. Это лишь удобная обёртка над механизмом прототипов, который лежит в основе JavaScript. Если вы захотите углубиться в тему — изучите прототипное наследование и цепочку прототипов. Это поможет понять язык на более глубоком уровне. Хорошее объяснение можно найти на doka.guide.

В следующем уроке подробнее рассмотрим массивы — один из самых используемых инструментов в повседневной разработке.