Классы: базовый синтаксис

Классы: базовый синтаксис #

class — объявление «типа» объекта с конструктором и методами. Синтаксис похож на классы в других языках, но в JavaScript это обёртка над прототипами: методы попадают на prototype, наследование строится через цепочку прототипов.


Объявление класса #

class Lesson {
  constructor(title, durationMin) {
    this.title = title
    this.durationMin = durationMin
    this.done = false
  }

  complete() {
    this.done = true
    return this
  }

  summary() {
    const status = this.done ? 'пройден' : 'в процессе'
    return `${this.title} (${this.durationMin} мин) — ${status}`
  }
}

const lesson = new Lesson('Замыкания', 25)
lesson.complete().summary()
// "Замыкания (25 мин) — пройден"

new обязателен — вызов Lesson() без new в классах выбросит ошибку.


constructor #

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

class UserProgress {
  constructor(userId) {
    if (!userId) {
      throw new Error('userId обязателен')
    }
    this.userId = userId
    this.completedLessons = []
  }
}

Логику валидации и значения по умолчанию держите в конструкторе; тяжёлую работу выносите в отдельные методы.


Методы экземпляра #

Методы в теле класса — короткая запись для функций на прототипе:

class Cart {
  constructor() {
    this.items = []
  }

  add(item) {
    this.items.push(item)
  }

  total() {
    return this.items.reduce((sum, { price }) => sum + price, 0)
  }
}

const cart = new Cart()
cart.add({ title: 'JSFlow Sticker', price: 150 })
cart.total() // 150

Стрелочные функции как поля класса (total = () => {}) создают свойство на каждом экземпляре — для обычных методов предпочтительны короткие методы в теле класса.


Геттеры и сеттеры #

Выглядят как свойства, но вызывают функции:

class StudyPlan {
  constructor(lessons) {
    this.lessons = lessons
  }

  get count() {
    return this.lessons.length
  }

  set count(value) {
    throw new Error('count только для чтения')
  }

  get estimatedHours() {
    const minutes = this.lessons.reduce((s, l) => s + l.durationMin, 0)
    return Math.round((minutes / 60) * 10) / 10
  }
}

const plan = new StudyPlan([
  { title: 'Операторы', durationMin: 20 },
  { title: 'Циклы', durationMin: 30 },
])

plan.count // 2
plan.estimatedHours // 0.8

Геттеры удобны для вычисляемых значений без вызова () в шаблонах.


Class expression #

Класс можно присвоить переменной или передать как значение:

const Formatter = class {
  constructor(locale) {
    this.locale = locale
  }

  formatDate(date) {
    return date.toLocaleDateString(this.locale)
  }
}

const ru = new Formatter('ru-RU')
ru.formatDate(new Date('2026-07-14')) // "14.07.2026"

Именованные class expression (class Name {}) видны только внутри выражения — полезно для отладки в стеке.


Подъём (hoisting) #

В отличие от function, объявление class не поднимается:

// ReferenceError: Cannot access 'Course' before initialization
// const c = new Course()

class Course {
  constructor(name) {
    this.name = name
  }
}

Объявляйте классы до использования или используйте class expression после присваивания.


Отличия от объекта-литерала #

class + newобъект { }
созданиеnew Lesson()const o = { }
прототипнастраивается цепочкойObject.prototype или Object.create
наследованиеextendsвручную через прототип
instanceofдазависит от цепочки

Классы уместны, когда много экземпляров с общим поведением; литерал — для единичных конфигов и простых структур.


Частые ошибки #

  1. Забыли newTypeError: Class constructor Lesson without new.
  2. Метод-стрелка в классе для наследования — поле экземпляра, не на прототипе; дочерние классы не переопределяют его через super в прототипной цепочке.
  3. Тяжёлая работа в constructor — блокирует создание; используйте ленивую инициализацию.
  4. Сеттер без валидации — любое присваивание ломает инварианты объекта.

Итог #

  • class задаёт конструктор и методы; под капотом — функция и прототип.
  • Методы в теле класса общие для экземпляров через prototype.
  • Геттеры и сеттеры оформляют вычисляемые и контролируемые свойства.
  • Классы не hoisting — объявляйте до создания экземпляров.

См. также #