Классы

ES6 представил концепцию «классов» в JavaScript, которая отличается от классов в других языках программирования. Здесь классы — это специальные функции, которые служат шаблонами для создания объектов, уже содержащих данные, свойства, связанные с этими данными, и методы, связанные с манипулированием этими данными. Эти объекты, свойства и методы вместе называются «членами» класса.

Чтобы определить класс, используйте ключевое слово class . Следуя передовому опыту и соглашению, установленному встроенными функциями-конструкторами JavaScript, любой идентификатор класса начинается с заглавной буквы:

class MyClass {}

Классы предназначены для предоставления более доступных способов работы с расширенными возможностями прототипов и функций конструктора:

class MyClass {}

typeof MyClass;
> "function"

Поскольку классы были частично добавлены для того, чтобы сделать работу с расширенными функциями JavaScript проще и привлекательнее, их иногда называют «синтаксическим сахаром» . Однако классы делают больше, чем просто предоставляют полезные сокращения для работы с прототипным наследованием . Введение синтаксиса классов создало возможности для решения давних проблем проектирования в JavaScript без возникновения проблем обратной совместимости. Например, весь код внутри тела класса всегда оценивается в строгом режиме .

Чтобы создать экземпляр класса, используйте new оператор.

class MyClass {}

const myClassInstance = new MyClass();

myClassInstance
;
> Object { }

Функции, определенные внутри тела класса, представляются как методы каждого экземпляра этого класса.

class MyClass {
    classMethod
() {
        console
.log( "My class method." );
   
}
}

const myClassInstance = new MyClass();

myClassInstance
.classMethod();
> "My class method."

Метод, определенный внутри класса, становится методом прототипа результирующего экземпляра. Из-за особенностей цепочки прототипов вы можете вызывать эти методы непосредственно на результирующем объекте:

class MyClass {
  classMethod
() {
    console
.log( "My class method." );
 
}
}

const myClassInstance = new MyClass( "A string." );

myClassInstance
;
> Object { }
   
<prototype>: Object { }
        classMethod
: function classMethod()
        constructor
: class MyClass { constructor(myPassedValue) }
       
<prototype>: Object { }

myClassInstance
.classMethod();
> "My class method."

Создание экземпляра класса вызывает специальный constructor() , который выполняет всю необходимую «настройку» вновь созданного экземпляра и инициализирует все связанные с ним свойства. Любые аргументы, передаваемые классу при создании экземпляра, доступны методу constructor() :

class MyClass {
  constructor
( myPassedValue ) {
    console
.log( myPassedValue );
 
}
}

const myClassInstance = new MyClass( "A string." );
> "A string."

Внутри тела класса значение this относится к самому экземпляру, при этом любые свойства, определенные в this представляются как свойства каждого экземпляра этого класса:

class MyClass {
  constructor
( myPassedValue ) {
   
this.instanceProperty = myPassedValue;
 
}
}

const myClassInstance = new MyClass( "A string." );

myClassInstance
;
> Object { instanceProperty: "A string." }

Эти свойства также доступны всем методам в теле класса:

class MyClass {
  constructor
( myPassedValue ) {
   
this.instanceProp = myPassedValue;
 
}
  myMethod
() {
    console
.log( this.instanceProp );
 
}
}

const myClassInstance = new MyClass( "A string." );

myClassInstance
.myMethod();
> "A string."

Если вы не определяете constructor() для своего класса, движок JavaScript предполагает пустой constructor «по умолчанию». Каждый класс может иметь только один специальный метод с именем constructor() :

class MyClass {
  constructor
() {}
  constructor
() {}
}
> Uncaught SyntaxError: A class may only have one constructor

Вы можете определить класс, используя либо объявление класса , либо выражение класса . Все предыдущие примеры представляли собой объявления классов, которые требуют вызова имен с использованием new . Выражениям класса можно дать имя или оставить его без имени, чтобы создать «анонимный» класс.

let ClassExpression = class {
    constructor
() {}
};

ClassExpression;
> class  {}

Единственное, для чего вы можете использовать выражения анонимного класса, — это функции, которые создают классы «на лету»:

function classMaker() {
 
return class {
    constructor
() {}
 
};
}

let
MyVariable = classMaker();

MyVariable;
> class  {}

Повторное объявление класса с использованием объявления класса приводит к синтаксической ошибке:


class MyClass {
    constructor
( ) {
        console
.log( "My class." );
   
}
};

class MyClass {
    constructor
() {
        console
.log( "My new class." );
   
}
};
> Uncaught SyntaxError: redeclaration of class MyClass

Однако выражения класса позволяют переопределить класс:

let ClassExpression = class MyClass { };

ClassExpression = class MyOtherClass {
    constructor
( myString ) {
       
this.myProp = myString;
   
}
};

new ClassExpression( "String." );
> MyOtherClass {myProp: 'String.'}

Вы не можете вызвать выражение именованного класса по имени так, как вы можете вызвать объявление класса. Однако назначенное имя выражения класса доступно как свойство созданного экземпляра, главным образом для облегчения отладки:

let MyVariable = class MyClass {};

MyClass;
> Uncaught ReferenceError: MyClass is not defined

MyVariable;
> class MyClass {}

MyVariable.name;
> "MyClass"

Когда вы инициализируете переменную с помощью выражения класса, правила подъема этой переменной соблюдаются, как и ожидалось. Объявления классов следуют тем же правилам «временной мертвой зоны», что и let и const , и ведут себя так, как будто они не были подняты на вершину своей текущей области действия, а это означает, что вызов класса до объявления класса вызывает ошибку:

{
    let myVar
= new MyClass( "Property string." );

   
class MyClass {
        myProp
;

        constructor
( myString ) {
           
this.myProp = myString;
       
}
   
};
};
> Uncaught ReferenceError: Cannot access 'MyClass' before initialization

Проверьте свое понимание

Что из следующего правильно определяет класс?

myClass = class {}
new class()
class MyClass {}

Сколько методов constructor() может иметь класс?

Никто
Один
Безлимитный