ES6 классы
1. ES6 классы
JavaScript является единственным массовым языком программирования с наследованием, основанным не на классах, а на прототипах. Огромное число разработчиков, владеющих техникой использования классов, постоянно пытались переделать JavaScript под свои умения, а главное, под имеющиеся наработки в области ООП. В ES6 сделали шаг навстречу и ввели класс, похожий на таковой в языках Java, C# и т. п. Это все те же прототипы, только в красивой обертке.
2. Объявление класса
Класс — это удобный способ для задания конструктора вместе с прототипом.
Преимущества использования классов:
Весь код внутри класса выполняется в строгом режиме.
Все методы являются неперечислимыми.
У всех методов класса отсутствует внутренний метод
[[Construct]]
, что означает появление ошибки при попытке использовать эти методы с операторомnew
.Вызов конструктора класса без оператора
new
вызовет ошибку.
Предположим, мы запустили отель и хотим, чтобы объект со свойствами и методами представлял каждого гостя.
//class declaration
class Guest {
//...
}
// Под капотом класс это функция-конструктор с прототипом
console.log(typeof Guest); // "function"
console.log(Guest.prototype); // {constructor: ƒ}
const guest = new Guest();
console.log(guest); // Guest {}
Copy
Как строить класс, зависит от того, что вам нужно. В нашем случае, класс представляет собой гостя отеля, поэтому мы добавим туда поля для имени и номера комнаты.
Класс использует аналог функции-конструктора — метод constructor
. Это особый метод, он должен присутствовать в объявлении класса обязательно. Назначение конструктора — создавать собственные свойства экземпляра класса.
Функция
constructor
запускается при вызовеnew Guest
, остальные методы записываются вGuest.prototype
.Свойство
prototype
класса доступно только для чтения, т.е. это свойство нельзя изменить.В классе должен быть только один конструктор, иначе будет ошибка.
class Guest {
// аналог функции-конструктора
constructor(name, roomNumber) {
this.name = name;
this.roomNumber = roomNumber;
}
}
const mango = new Guest('Mango', 26);
console.log(mango); // {name: Mango, roomNumber: 26}
console.log(mango instanceof Guest); // true
console.log(mango instanceof Object); // true
Copy
3. Методы
Добавим функцию getFullInfo
. Функции, определенные таким образом, называться методами класса и доступны всем экземплярам через prototype
.
class Guest {
// Аналог функции-конструктора
constructor(name, roomNumber) {
this.name = name;
this.roomNumber = roomNumber;
}
// Аналог Guest.prototype.getFullInfo
getFullInfo() {
console.log(`
Guest ${this.name}
Room number ${this.roomNumber}
`);
}
}
const mango = new Guest('Mango', 26);
mango.getFullInfo();
// Guest Mango
// Room number 26
Copy
4. Геттеры и сеттеры
Собственные свойства класса желательно хранить в constructor
. Но существует и другой вариант — разместить в теле класса методы set
и get
. Эти методы используют особый синтаксис, а при их вызове, после имени объекта следует написать только имя геттера или сеттера без вызова функции, т.е. без круглых скобок.
class Guest {
// Собственные свойства класса размещаем в конструкторе
constructor(name, roomNumber) {
this.name = name;
this.roomNumber = roomNumber;
}
// Используем геттеры и сеттеры для описания интерфейса доступа к свойствам
get name() {
return this.name;
}
set name(value) {
this.name = value;
}
}
const mango = new Guest('Mango', 26);
// обращение к get и set не требует вызова - т.е. без ()
console.log(mango.name); // Mango
mango.name = 'Mango the Fluffy';
console.log(mango.name); // Mango the Fluffy
Copy
5. Статические свойства и методы
Можно создавать собственные свойства класса и собственные методы класса для вызова по имени класса без создания объекта. Такие свойства и методы называют статическими. Для их создания в классе перед свойством или методом нужно добавить служебное слово static
.
Конструктор класса тоже метод, но его нельзя делать статическим, это вызовет ошибку.
// Класс со статическими свойствами и методами
class Calc {
// Класс-калькулятор для двух аргументов
constructor() {}
// Метод как замена свойству
static get PI() {
return 3.14;
}
// Статический метод +
static add(...args) {
return args.reduce((acc, next) => acc + next, 0);
}
// Статический метод *
static mult(...args) {
return args.reduce((acc, next) => acc * next, 1);
}
}
console.log(Calc.PI); // 3.14
console.log(Calc.add(2, 3, 4)); // 9
console.log(Calc.mult(12, 3, 4)); // 144
Copy
6. Наследование
JavaScript позволяет реализовать наследование классов. Это означает, что мы можем создавать новые классы, которые наследуют все от другого класса, но при этом добавляют уникальную информацию для себя.
/*
* Ключевое слово extends указывает на родительский класс,
* чьи свойства будут унаследованы.
*/
class Child extends Parent {
// ...
}
Copy
Создадим базовый класс-родитель Animal
от которого класс Dog
будет наследовать.
class Animal {
constructor(name) {
this.name = name;
}
move() {
console.log(`I, ${this.name}, am moving!`);
}
}
class Dog extends Animal {
constructor(name, breed) {
// Вызвать конструктор Animal с аргументом name
super(name);
this.breed = breed;
}
bark() {
console.log('woof!');
}
moveAndMakeSound() {
super.move();
this.bark();
}
}
const dog = new Dog('Mango', 'shepherd');
dog.move(); // I, Mango, am moving!
dog.bark(); // woof!
dog.moveAndMakeSound(); // I, Mango, am moving! woof!
Copy
При наследовании через extends
формируется стандартная цепочка прототипов: методы Dog
находятся в Dog.prototype
, методы Animal
в Animal.prototype
и они связаны через __proto__
.
Конструктор родителя наследуется автоматически. То есть, если в потомке не указан свой constructor
, то используется родительский. Если же у потомка свой constructor
, то чтобы в нём вызвать конструктор родителя, используется метод super()
с аргументами для constructor
родителя.
Вызвать конструктор родителя можно только изнутри конструктора потомка. В частности,
super()
нельзя вызвать из произвольного метода.В конструкторе потомка мы обязаны вызвать
super()
до первого обращения к ключевому словуthis
. До вызоваsuper()
не существуетthis
, так как по спецификации в этом случае именноsuper
инициализируетthis
.super()
можно вызывать только в наследующем классе, иначе будет ошибка.При наследовании, вызов конструктора родителя осуществляется через
super(...args)
, вызов родительских методов черезsuper.method(...args)
.
7. Дополнительные материалы
Last updated