Что такое ООП

Что такое ООП

Технический фундамент объектной модели в JS

В JavaScript объекты устроены через прототипную модель:

  • данные хранятся в самом экземпляре;
  • методы обычно разделяются через прототип и переиспользуются;
  • class-синтаксис (следующие уроки) упрощает запись, но не меняет фундаментальную механику;
  • корректный дизайн модели важнее, чем выбор "класс vs функция" сам по себе.

Это важно, потому что ООП в JS надо понимать как способ проектирования сущностей, а не как набор "обязательных классов".

Почему тема ООП появляется в JavaScript

Когда проект растет, простой набор функций и объектов иногда перестает быть удобным. Логика начинает дублироваться, связи между данными и действиями разъезжаются, а изменения в одном месте ломают другое. ООП (объектно-ориентированное программирование) помогает организовать код вокруг сущностей предметной области.

Ключевой момент: ООП это не "магия классов", а способ структурировать состояние и поведение вместе.

Проверь себя: почему в большом проекте неудобно держать данные в одном модуле, а функции, работающие с ними, в другом без четких границ?

Базовая идея ООП простыми словами

В ООП ты описываешь сущности как объекты. У объекта есть:

  • состояние (данные, свойства);
  • поведение (действия, методы).

Например, у сущности User состояние это name, email, role, а поведение это login(), logout(), changeEmail().

const user = {
  name: 'Аня',
  email: 'anya@example.com',
  login() {
    return `${this.name} вошел в систему`;
  },
};

console.log(user.login());

Смотри, что важно: данные и действия рядом, поэтому модель легче понимать и поддерживать.

Основные принципы ООП (без перегруза)

На старте достаточно понимать 4 идеи:

  1. Инкапсуляция - скрывать внутренние детали и давать наружу только нужный интерфейс.
  2. Абстракция - работать с объектом через понятные методы, не думая о внутренних шагах.
  3. Наследование - создавать новую сущность на основе существующей.
  4. Полиморфизм - одинаковый интерфейс, но разное поведение у разных сущностей.

Смотри, что важно: в JavaScript полиморфизм часто проявляется не через extends, а через "контракт поведения": объект просто должен иметь метод с нужным именем.

function printLabel(entity) {
  // Нам не важно, какого класса объект. Нам важно, что у него есть getLabel()
  console.log(entity.getLabel());
}

const user = { getLabel: () => 'User: Анна' };
const order = { getLabel: () => 'Order: #14' };

printLabel(user);
printLabel(order);

Здесь часто путаются: в реальной разработке не всегда нужно применять все 4 принципа сразу. Важно выбрать то, что реально упрощает код, а не усложняет архитектуру.

Проверь себя: какой принцип помогает спрятать сложную внутреннюю логику за простым методом pay()?

ООП и реальные продуктовые сценарии

  1. Интернет-магазин.
  • Product хранит цену и остаток.
  • Cart управляет добавлением и удалением товаров.
  • Order считает итог и статус.
  1. Система ролей пользователя.
  • User как базовая сущность.
  • методы проверки прав, смены профиля, управления доступом.
  1. UI-компоненты.
  • общий класс для компонентов с методами mount, render, destroy.
  • специализированные компоненты переиспользуют базовую логику.

В каждом сценарии ООП помогает держать код ближе к бизнес-модели.

Чем ООП отличается от "просто набора функций"

В процедурном стиле ты часто передаешь объект в разные функции:

function login(user) {
  return `${user.name} вошел`;
}

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

Когда ООП полезно, а когда избыточно

Полезно:

  • сложная бизнес-доменная логика;
  • много похожих сущностей с общим поведением;
  • долгоживущий проект с командной разработкой.

Избыточно:

  • маленький скрипт на 30 строк;
  • одноразовая утилита;
  • простая трансформация данных без состояния.

Анти-провал: не превращай ООП в религию. Иногда функция проще и лучше класса.

Частые ошибки новичков

  • Делать классы "на всякий случай", даже где не нужно.
  • Смешивать слишком много ответственности в одной сущности (User и валидация, и сеть, и UI).
  • Нарушать инкапсуляцию: менять внутренние поля объекта из любого места.
  • Считать, что ООП автоматически делает код "профессиональным".
// Плохо: слишком много ролей у одной сущности
class AppManager {
  // сеть, UI, платежи, аналитика, валидация — всё внутри
}

Дополнительный пример: простой объект с инвариантом состояния.

const cart = {
  items: [],
  addItem(item) {
    if (!item || typeof item.price !== 'number' || item.price < 0) return;
    this.items.push(item);
  },
  getTotal() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  },
};

Лучше разбивать ответственность на отдельные сущности.

Что будет, если изменить входные данные

Если в объекте user из первого примера name будет '', метод login() вернет некорректное сообщение. Значит, модель данных и валидация важны даже в ООП. Класс или объект не "лечит" плохой вход автоматически.

Проверь себя: где лучше проверять корректность name - в момент создания сущности или в каждом методе?

Краткий итог

  • ООП это способ организовать код вокруг сущностей с данными и поведением.
  • Важные идеи: инкапсуляция, абстракция, наследование, полиморфизм.
  • ООП помогает в сложных продуктовых сценариях, где есть состояние и повторяемая логика.
  • Используй ООП осознанно: не везде класс лучше функции.
  • Главная цель ООП - сделать систему понятной, расширяемой и устойчивой к изменениям.