Использование классов в JavaScript: от основ до продвинутых примеров

Раздел: Программирование на JavaScript -> Объектно-ориентированное программирование в JavaScript

Основы классов в JavaScript

Синтаксис class появился в ECMAScript 2015 и предлагает наиболее понятный способ реализации объектно-ориентированного подхода. Класс объявляется с помощью ключевого слова class и содержит конструктор, методы, геттеры/сеттеры и статические свойства.

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  greet() {
    return `Привет, меня зовут ${this.name}`;
  }
  static isAdult(age) {
    return age >= 18;
  }
}

Js class (классы в javascript)

Конструктор вызывается при создании экземпляра оператором new. Методы, объявленные внутри класса, автоматически попадают в прототип, а статические методы принадлежат самому классу.

const alice = new Person('Алиса', 25);
console.log(alice.greet()); // Привет, меня зовут Алиса
console.log(Person.isAdult(25)); // true

Типичные ошибки:

  • Забыть new при вызове конструктора – в строгом режиме это вызывает TypeError.
  • Потеря контекста this при передаче метода как колбэка. Решение – стрелочная функция в конструкторе или bind.
// Ошибка: this будет undefined
const greet = alice.greet;

greet(); // TypeError: Cannot read properties of undefined (reading 'name')
// Исправление
class Person {
  constructor(name) {
    this.name = name;
    this.greet = () => `Привет, ${this.name}`;
  }
}

Как создать объект с методами без синтаксиса class?

До ES5 использовались функции-конструкторы и прототипное наследование. Этот подход остаётся рабочим, но уступает классам в читаемости.

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.greet = function() {
  return `Привет, меня зовут ${this.name}`;
};
Person.isAdult = function(age) {
  return age >= 18;
};

Проблемы: необходимость вручную управлять прототипом, отсутствие чёткого синтаксиса для статических свойств, сложности с наследованием.

Забывание new – свойства запишутся в глобальный объект. Исправление: проверка if (!(this instanceof Person)) return new Person(name, age);

Как сделать фабричную функцию вместо класса?

Фабрики возвращают объект без использования new. Удобны для создания объектов с приватными данными через замыкания.

function createPerson(name, age) {
  return {
    name,
    age,
    greet() {
      return `Привет, меня зовут ${name}`;
    }
  };
}
const bob = createPerson('Боб', 30);

Отсутствует наследование через прототип – каждый экземпляр копирует методы, что увеличивает расход памяти. Применяется для простых объектов или когда нужна истинная инкапсуляция.

Нельзя проверить принадлежность объекта фабрике с помощью instanceof – результат всегда false.
Как использовать классовые выражения?

Классы можно объявить как выражения, а не декларации. Это позволяет, например, динамически создавать классы или передавать их как аргументы.

const Animal = class {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} издаёт звук`);
  }
};
const dog = new Animal('Собака');
dog.speak(); // Собака издаёт звук

Имя классового выражения может быть опущено или задано только для внутреннего использования. Используется в паттерне «Примесь» (mixin) или при создании анонимных классов.

При отладке безымянный класс отображается как class – сложнее определить источник ошибки. Рекомендуется давать имена выражениям.
Пример
// Миксины: расширение функциональности через примеси
const sayMixin = {
  sayHi() {
    console.log(`Привет, ${this.name}`);
  }
};
class User {
  constructor(name) {
    this.name = name;
  }
}
Object.assign(User.prototype, sayMixin);
const user = new User('Елена');
user.sayHi(); // Привет, Елена
Вывод: Привет, Елена
Пример
// Наследование встроенных классов
class MyArray extends Array {
  first() {
    return this[0];
  }
  last() {
    return this[this.length - 1];
  }
}
const arr = new MyArray(1, 2, 3);
console.log(arr.first()); // 1
console.log(arr.last());  // 3
console.log(arr instanceof Array); // true
1
3
true
Пример
// Статические блоки инициализации (ES2022)
class Config {
  static {
    this.defaultTimeout = 5000;
    this.defaultUrl = 'https://api.example.com';
  }
}
console.log(Config.defaultTimeout); // 5000
5000
Пример
// Приватные поля (ES2022)
class BankAccount {
  #balance = 0;
  deposit(amount) {
    if (amount < 0) throw new Error('Неверная сумма');
    this.#balance += amount;
  }
  getBalance() {
    return this.#balance;
  }
}
const acc = new BankAccount();
acc.deposit(100);
console.log(acc.getBalance()); // 100
// console.log(acc.#balance); // SyntaxError: Private field
100
Пример
// Проверка принадлежности через instanceof
class Animal {}
class Dog extends Animal {}
const dog = new Dog();
console.log(dog instanceof Dog);     // true
console.log(dog instanceof Animal);  // true
console.log(dog instanceof Object);  // true
true
true
true

Классы в JavaScript - comments

En
Js class (javascript)