#8 Javascript классы

poster
В es6 были добавлены классы. Мы разберем чем они отличаются от прототипов и как их описывать. Познакомимся с constructor, super, прототипными и статическими методами.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В том уроке мы с вами разберем, как писать классы в ecmascript 6.

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

В javascript не существует классов и в ес5 мы использовали функции и прототипы, чтобы описывать классы. В ес6 не придумали ничего нового. Просто добавили синтаксический сахар для описания все тех же прототипов.

Как же выглядит класс описаный с помощью классов ес6?

class SimpleDate {
  constructor (year, month, day) {
    this.year = year;
    this.month = month;
    this.day = day;
  }
}

const today = new SimpleDate(2017, 1, 28)
console.log(today)

с помощью слова class мы описали новый класс. Также мы добавили метод constructor, который принимает year, month, day и записывает их в this. Мы создали переменную today, которая является екземпляром класса SimpleDate.

Давайте добавим метод toString, который будет возвращать дату в человеческом формате

class SimpleDate {
  constructor (year, month, day) {
    this.year = year;
    this.month = month;
    this.day = day;
  }

  toString () {
    return `${this.day}/${this.month}/${this.year}`;
  }
}

const today = new SimpleDate(2017, 1, 28)
console.log(today.toString())

Теперь у екземпляра класса появился метод toString, вызывая который мы получаем красивый вывод даты.

Также мы можем использовать наследование в классах с помощью слова extend. Давайте создадим класс OtherDate, который будет наследоваться от SimpleDate.

class OtherDate extends SimpleDate {
}

Для того, чтобы выполнить конструктор парент класса мы используем метод super и передаем в него аргументы. Super используется для того, чтобы обращатся к родительскому классу.

class OtherDate extends SimpleDate {
  constructor(year, month, day) {
    super(year, month, day)
  }
}
const tomorrow = new OtherDate(2017, 1, 29)
console.log(tomorrow.toString())

Как вы видите, мы вызвали конструктор парента и также у нас есть доступ к всем методам из парент класса. Именно поэтому метод toString у нас сработал

Давайте теперь пеопределим метод toString с другим выводом

class OtherDate extends SimpleDate {
  constructor(year, month, day) {
    super(year, month, day)
  }

  toString () {
    return `${this.day}.${this.month}.${this.year}`;
  }
}

Не нужно думать, что классы в ес6 это какая-то магия. Если мы посмотрим, что такое класс SimpleDate, то увидим, что это просто функция

typeof SimpleDate

То есть классы создают обычные функции с прототипным наследованием. Но вы не можете вызвать класс напрямую как функцию

SimpleDate()

У нас вывалится ошибка

TypeError: Classes can’t be function-called

потому-что классы нельзя вызывать напрямую.

Описав метод toString мы описывали метод прототипа

Также классам можно добавлять кроме прототипных методов, статические методы. Они будут является методами самого класса, а не методами prototype.

Если мы напишем в классе OtherDate метод hello

static hello() {
  console.log('hello OtherDate');
}

То мы можем вызвать его с помощью OtherDate.hello(). В прототипах он доступен не будет.

И на последок пища для размышлений о классах. В Javascript коммьюнити классы считаются весьма спорным функционалом javascript. И применять их нужно с оглядкой. Например многие люди предпочитают писать модуль с набором функций, чем класс. Их легче поддерживать, експортировать и переиспользовать, не приходится использовать this и не нужно постоянно помнить а какой у меня контекст. Также нет проблем с кучей классов, которые наследуются друг от друга и сложно отдебажить какой метод откуда доступен. Поэтому лучше два раза подумайте прежде чем их использовать.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Sniper Night
6 лет назад
В тект урока вкралась досадная опечатка. екземпляр вместо экземпляр.
Petr Pozhoga
6 лет назад
Здравствуйте, а как наследоватся от 2 классов сразу (без примесей), например class OtherDate extends SimpleDate, someDate ?
monsterlessons
6 лет назад
Добрый день, никак. OtherDate extends SimpleDate это просто сахар над обычными прототипами из js. В js невозможно наследоваться больше чем от одного прототипа. Когда вы видите, что код выглядит так, как будет идет наследование от нескольких классов, то создается просто несколько родительских прототипов. То, что вы видите справа от extends может быть каким угодно кодом, который вы потом можете использовать для того чтобы скомбинировать прототипы.
Guru-Js
8 лет назад
Зачем в OtherDate продублировал метод toString()? Ведь если в constructor класcа OtherDate есть super можем взять toString() с родителя SimpleData
monsterlessons
8 лет назад
Конечно можно, но мы его хотим переопределить(т.е. сделать отдельную реализацию для OtherDate), поэтому мы его и описываем в OtherDate.
Moe Green
8 лет назад
Можно ли сказать так - JavaScript изначально был создан как функциональный язык и у него не было и нет поддержки полноценных классов? А все попытки "создать" таковые - это притянуть ситуацию за уши? И точно также с асинхронностью? У меня пока что мозги склеиваются от все этих Promise и async-await ))
monsterlessons
8 лет назад
Он не функциональный вообще, но у него не было и нет поддержки полноценных классов. Да это попытки создать таковые Async await - это такое же сахар вокруг промисов как и class вокруг prototype.
Valerii Kuzivanov
9 лет назад
Пока не понятно в чем сложность работы с классами нежели с функциями и прототипами. Я из php вернулся, так там вполне себе удобно классы реализованы.
monsterlessons
9 лет назад
Сложность в том, что в php есть нормальный классы как сущность, а в javascript нет. И для реализации классов используется костыль в виде прототипов.
Evgeny Listopad
9 лет назад
Будешь делать видео уроки по typescript?
monsterlessons
9 лет назад
В планах есть, но пока не хватает времени.
Valerii Kuzivanov
8 лет назад
Спустя 11 месяцев активного использования JS, скажу: Я так и не нашел толковое применение классов =) Единственно где используем так это в react/angular в качестве обертки для компонента. В том же node.js как по мне проще сделать module.exports = {//... тут методы} Всё равно приватных методов нету, наследовать особо нечего, я хз. Надеюсь через 11 мес появится другое мнение)))
monsterlessons
8 лет назад
Ну на вкус и цвет. Я считаю, что если вам что-то кажется ненужным, то просто не используйте его (как вы, собственно, и делаете). P.S. можете попробовать Typescript там классы повеселее будут.
Valerii Kuzivanov
8 лет назад
Спустя 4 месяца вернулся сообщить, что нашел применение Классу!!! На днях пилил плагин-обертку на Vue.js для работы с websockets, так вот там класс зашел как никогда кстати! При создании экземпляра принимает url и опции и реализовывает приватные и открытые методы, также засунул туда паттерн Observer. Получилось красиво в компонентах выглядит так: this.$ws.connect(), this.$ws.reconnect(), this.$ws.on('eventName', callback) и тд.
monsterlessons
8 лет назад
Поздравляю) Рад, что получилось.