Классы
С внедрением стандарта ES2015 (ES6) в JavaScript появился новый способ определения объектов - с помощью классов. Класс представляет описание объекта, его состояния и поведения, а объект является конкретным воплощением или экземпляром класса.
Опредление класса
Для определения класса используется ключевое слово class
. Это наиболее расспространенный способ определения класса. После слова class
идет название класса, в данном случае класс называется Person
, и затем в фигурных скобках определяется тело класса:
class Person{ }
Есть и другие способы, можно определить анонимный класс и присвоить его переменной или константе:
const Person = class{}
В принципе мы можем создать и неанонимный класс и присвоить его переменной или константе:
const User = class Person{}
Создание объектов
Класс - это общее представление некоторых сущностей или объектов. Конкретным воплощением этого представления, класса является объект. И после определения класса мы можем создать объекты класса с помощью конструктора:
class Person{}
const tom = new Person();
const bob = new Person();
Для создания объекта с помощью конструктора сначала ставится ключевое слово new
. Затем собственно идет вызов конструктора - по сути вызов функции по имени класса. По умолчанию классы имеют один конструктор без параметров. Поэтому в данном случае при вызове конструктора в него не передается никаких аргументов.
Стоит отметить, что в отличие от функций, чтобы использовать класс, его надо сначала оределить. Например, в следующем коде мы получим ошибку, так как пытаемся использовать класс до его определения:
// ! Ошибка - Uncaught ReferenceError: Cannot access 'Person' before initialization
const tom = new Person();
class Person{}
Если определение класса присвоено переменной или константе, то мы можем использовать имя этой переменной/константы для создания объектов класса:
const User = class Person{}
const tom = new User();
console.log(tom);
Выше в коде несмотря на то, что мы используем вызов new User()
, в реальности создаваемый объект будет представлять класс Person
.
Пример создания объекта анонимного класса:
const Person = class{}
const tom = new Person();
console.log(tom);
Поля и свойства класса
Для хранения данных или состояния объекта в классе используются поля и свойства.
Итак, выше был определен класс Person
, который представлял человека. У человека есть отличительные признаки, например, имя и возраст. Определим в классе Person
поля для хранения этих данных:
class Person{
name;
age;
}
const tom = new Person();
tom.name = "Tom";
tom.age = 37;
// Tom
console.log(tom.name);
// 37
console.log(tom.age);
Определение поля фактически просто представляет его название:
name;
age;
Так, здесь определено поле name
для хранения имени человека, и поле age
для хранения возраста человека. После создания объекта класса мы можем обратиться к этим полям. Для этого после имени объекта через точку указывается имя поля:
// установим значение поля
tom.name = "Tom";
// получим значение свойства
console.log(tom.name);
В примере выше поля класса также можно назвать свойствами. По сути свойства представляют доступные извне или публичные поля класса. Дальше мы подробно разберем, когда поля бывают непубличные, то есть недоступными извне. Но пока стоит понимать, что свойства и публичные поля - это одно и то же. И в примере выше поля name
и age
также можно назвать свойствами. При необходимости мы можем присвоить полям некоторые начальные значения:
class Person{
name = "Unknown";
age= 18;
}
const tom = new Person();
// Unknown
console.log(tom.name);
tom.name = "Tom";
// Tom
console.log(tom.name);
Поведение класса и его методы
Кроме хранения данных, которые определяют состояние объекта, класс может иметь методы, которые определяют поведение объекта - действия, которые выполняет объект. Например, определим в классе Person
пару методов:
class Person{
name;
age;
move(place){
console.log(`Go to ${place}`);
}
eat(){
console.log("Eat apples");
}
}
const tom = new Person();
// Go to Hospital
tom.move("Hospital");
// Go to Cinema
tom.move("Cinema");
// Eat apples
tom.eat();
Здесь определен метод move()
, который представляет условное передвижение человека. В качестве параметра метод принимает место, к которому идет человек. Второй метод eat()
представляет условный процесс питания.
Обращение к полям и методам внутри класса через this
Что если мы хотим в методах класса обратиться к полям класса или к другим его методам? В этом случае перед именем поля/свойства или метода указывается ключевое слово this
, которое в данном случае указывает на текущий объект.
Например, определим метод, который выводит информацию об объекте:
class Person{
name;
age;
print(){
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person();
tom.name = "Tom";
tom.age = 37;
// Name: Tom Age: 37
tom.print();
const bob = new Person();
bob.name = "Bob";
bob.age = 41;
// Name: Bob Age: 41
bob.print();
Определение конструктора
Для создания объекта класса используется конструктор:
const bob = new Person();
Вызов конструктора по умолчанию, который есть в классах, фактически представляет вызов метода, который имеет то же название, что и класс, и возвращает объект этого класса.
Но также мы можем определить в классах свои конструкторы:
class Person{
name;
age;
constructor(){
console.log("Вызов конструктора");
}
print(){
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
// Вызов конструктора
const tom = new Person();
// Вызов конструктора
const bob = new Person();
Конструктор определяется с помощью метода с именем constructor
. По сути это обычный метод, который может принимать параметры. В данном случае конструктор просто выводит на консоль некоторое сообщение. Соответственно при выполнении строки:
const tom = new Person();
Мы увидим в консоли браузера соответствующее сообщение.
Как правило, цель конструктора - инициализация объекта некоторыми начальными данными:
class Person{
name;
age;
constructor(personName, personAge){
this.name = personName;
this.age = personAge;
}
print(){
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person("Tom", 37);
// Name: Tom Age: 37
tom.print();
const bob = new Person("Bob", 41);
// Name: Bob Age: 41
bob.print()
Здесь конструктор принимает два параметра и передает их значения полям класса. Соответственно при создании объекта мы можем передать в конструктор соответствующие значения для этих параметров:
const tom = new Person("Tom", 37);
Стоит отметить, что в примере выще определения полей класса избыточно. Обращение в конструкторе к полям через this
фактически будет аналогично их определению, и в данном случае мы можем убрать определение полей:
class Person{
constructor(personName, personAge){
this.name = personName;
this.age = personAge;
}
print(){
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person("Tom", 37);
// Name: Tom Age: 37
tom.print();
const bob = new Person("Bob", 41);
// Name: Bob Age: 41
bob.print()