Movatterモバイル変換


[0]ホーム

URL:


  1. Веб-технологии для разработчиков
  2. JavaScript
  3. Справочник по JavaScript
  4. Классы

This page was translated from English by the community.Learn more and join the MDN Web Docs community.

View in EnglishAlways switch to English

Классы

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since ⁨март 2016 г.⁩.

Классы в JavaScript были введены в ECMAScript 2015 и представляют собой синтаксический сахар над существующим в JavaScript механизмом прототипного наследования. Синтаксис классовне вводит новую объектно-ориентированную модель, а предоставляет более простой и понятный способ создания объектов и организации наследования.

Определение классов

На самом деле классы — это "специальныефункции", поэтому точно также, как вы определяете функции (function expressions иfunction declarations), вы можете определять и классы с помощью:class declarations иclass expressions.

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

Первый способ определения класса —class declaration (объявление класса). Для этого необходимо воспользоваться ключевым словомclass и указать имя класса (в примере — «Rectangle»).

js
class Rectangle {  constructor(height, width) {    this.height = height;    this.width = width;  }}

Подъём (hoisting)

Разница междуобъявлением функции (function declaration) иобъявлением класса (class declaration) в том, чтообъявление функции совершает подъём (hoisting), в то время какобъявление класса — нет. Поэтому вначале необходимо объявить ваш класс и только затем работать с ним, а код же вроде следующего сгенерирует исключение типаReferenceError:

js
var p = new Rectangle(); // ReferenceErrorclass Rectangle {}

Выражение класса

Второй способ определения класса —class expression (выражение класса). Можно создавать именованные и безымянные выражения. В первом случае имя выражения класса находится в локальной области видимости класса и может быть получено через свойства самого класса, а не его экземпляра.

js
// безымянныйvar Rectangle = class {  constructor(height, width) {    this.height = height;    this.width = width;  }};console.log(Rectangle.name);// отобразится: "Rectangle"// именованныйvar Rectangle = class Rectangle2 {  constructor(height, width) {    this.height = height;    this.width = width;  }};console.log(Rectangle.name);// отобразится: "Rectangle2"

Примечание:Выражения класса подвержены тем же проблемам с подъёмом (hoisting), что иобъявления класса.

Тело класса и задание методов

Тело класса — это часть кода, заключённая в фигурные скобки{}. Здесь вы можете объявлять члены класса, такие как методы и конструктор.

Строгий режим

Телаобъявлений классов ивыражений классов выполняются в строгом режиме (strict mode).

Constructor

Методconstructor — специальный метод, необходимый для создания и инициализации объектов, созданных, с помощью класса. В классе может быть только один метод с именемconstructor. Исключение типаSyntaxError будет выброшено, если класс содержит более одного вхождения методаconstructor.

Ключевое словоsuper можно использовать в методеconstructor для вызова конструктора родительского класса.

Методы прототипа

Смотрите такжеопределение методов.

js
class Rectangle {  constructor(height, width) {    this.height = height;    this.width = width;  }  get area() {    return this.calcArea();  }  calcArea() {    return this.height * this.width;  }}const square = new Rectangle(10, 10);console.log(square.area); // 100

Статические методы и свойства

Ключевое словоstatic, определяет статический метод или свойства для класса. Статические методы и свойства вызываются безинстанцирования их класса, ине могут быть вызваны у экземпляров (instance) класса. Статические методы, часто используются для создания служебных функций для приложения, в то время как статические свойства полезны для кеширования в рамках класса, фиксированной конфигурации или любых других целей, не связанных с реплецированием данных между экземплярами.

js
class Point {  constructor(x, y) {    this.x = x;    this.y = y;  }  static displayName = "Точка";  static distance(a, b) {    const dx = a.x - b.x;    const dy = a.y - b.y;    return Math.hypot(dx, dy);  }}const p1 = new Point(5, 5);const p2 = new Point(10, 10);p1.displayName; //undefinedp1.distance; //undefinedp2.displayName; //undefinedp2.distance; //undefinedconsole.log(Point.displayName); // "Точка"console.log(Point.distance(p1, p2)); // 7.0710678118654755

Привязкаthis в прототипных и статических методах

Когда статический или прототипный метод вызывается без привязки к this объекта (или когда this является типом boolean, string, number, undefined, null), тогда this будет иметь значение undefined внутри вызываемой функции. Поведение будет таким же даже без директивы"use strict", потому что код внутри тела класса всегда выполняется в строгом режиме.

js
class Animal {  speak() {    return this;  }  static eat() {    return this;  }}let obj = new Animal();obj.speak(); // объект Animallet speak = obj.speak;speak(); // undefinedAnimal.eat(); // класс Animallet eat = Animal.eat;eat(); // undefined

Если мы напишем этот же код используя классы основанные на функциях, тогда произойдёт автоупаковка основанная на значении this, в течение которого функция была вызвана. В строгом режиме автоупаковка не произойдёт - значение this останется прежним.

js
function Animal() {}Animal.prototype.speak = function () {  return this;};Animal.eat = function () {  return this;};let obj = new Animal();let speak = obj.speak;speak(); // глобальный объект (нестрогий режим)let eat = Animal.eat;eat(); // глобальный объект (нестрогий режим)

Свойства экземпляра

Свойства экземпляра должны быть определены в методе класса:

class Rectangle {  constructor(height, width) {    this.height = height;    this.width = width;  }}

Статические (class-side) свойства и свойства прототипа должны быть определены за рамками тела класса:

Rectangle.staticWidth = 20;Rectangle.prototype.prototypeWidth = 25;

Определение полей

Предупреждение:Публичные и приватные поля - этоэкспериментальная особенность (stage 3), предложенная комитетомTC39 по стандартам языка Javascript. Поддержка браузерами ограничена, но это нововведение может быть использовано на моменте сборки, используя к примеруBabel.

Публичные поля

Используя Javascript синтаксис определения полей, приведённый выше пример может быть изменён следующим образом:

class Rectangle {  height = 0;  width;  constructor(height, width) {    this.height = height;    this.width = width;  }}

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

Более подробно об этом написано впубличные поля класса.

Приватные поля

Предыдущий пример может быть изменён следующим образом, используя приватные поля:

class Rectangle {  #height = 0;  #width;  constructor(height, width) {    this.#height = height;    this.#width = width;  }}

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

Примечание:Приватные поля могут быть объявлены только заранее в объявлении поля.

Приватные поля не могут быть созданы позже путём присваивания им значения, в отличии от обычных свойств.

Более подробно об этом написано вПриватные поля класса.

Наследование классов с помощьюextends

Ключевое словоextends используется вобъявлениях классов ивыражениях классов для создания класса, дочернего относительно другого класса.

js
class Animal {  constructor(name) {    this.name = name;  }  speak() {    console.log(`${this.name} издаёт звук.`);  }}class Dog extends Animal {  constructor(name) {    super(name); // вызывает конструктор super класса и передаёт параметр name  }  speak() {    console.log(`${this.name} лает.`);  }}let d = new Dog("Митци");d.speak(); // Митци лает

Если в подклассе присутствует конструктор, он должен сначала вызвать super, прежде чем использовать this.

Аналогичным образом можно расширять традиционные, основанные на функциях "классы":

js
function Animal(name) {  this.name = name;}Animal.prototype.speak = function () {  console.log(`${this.name} издаёт звук.`);};class Dog extends Animal {  speak() {    console.log(`${this.name} лает.`);  }}let d = new Dog("Митци");d.speak(); // Митци лает// Для аналогичных методов дочерний метод имеет приоритет над родительским.

Обратите внимание, что классы не могут расширять обычные (non-constructible) объекты. Если вам необходимо создать наследование от обычного объекта, в качестве замены можно использоватьObject.setPrototypeOf():

js
var Animal = {  speak() {    console.log(`${this.name} издаёт звук.`);  },};class Dog {  constructor(name) {    this.name = name;  }}// Если вы этого не сделаете, вы получите ошибку TypeError при вызове speak.Object.setPrototypeOf(Dog.prototype, Animal);let d = new Dog("Митци");d.speak(); // Митци издаёт звук.

Species

Допустим, вам хотелось бы возвращать объекты типаArray в вашем производном от массива классеMyArray. Паттерн species позволяет вам переопределять конструкторы по умолчанию.

Например, при использовании таких методов, какmap(), который возвращает конструктор по умолчанию, вам хотелось бы, чтобы они возвращали родительский объектArray вместо объектаMyArray. СимволSymbol.species позволяет это реализовать:

js
class MyArray extends Array {  // Изменить species на родительский конструктор Array  static get [Symbol.species]() {    return Array;  }}var a = new MyArray(1, 2, 3);var mapped = a.map((x) => x * x);console.log(mapped instanceof MyArray); // falseconsole.log(mapped instanceof Array); // true

Обращение к родительскому классу с помощьюsuper

Ключевое словоsuper используется для вызова функций на родителе объекта.

js
class Cat {  constructor(name) {    this.name = name;  }  speak() {    console.log(`${this.name} издаёт звук.`);  }}class Lion extends Cat {  speak() {    super.speak();    console.log(`${this.name} рычит.`);  }}let l = new Lion("Фаззи");l.speak();// Фаззи издаёт звук.// Фаззи рычит.

Mix-ins

Абстрактные подклассы, или mix-ins, — это шаблоны для классов. У класса в ECMAScript может быть только один родительский класс, поэтому множественное наследование (к примеру, от tooling classes) невозможно. Функциональность должен предоставлять родительский класс.

Для реализации mix-ins в ECMAScript можно использовать функцию, которая в качестве аргумента принимает родительский класс, а возвращает подкласс, его расширяющий:

js
var calculatorMixin = (Base) =>  class extends Base {    calc() {}  };var randomizerMixin = (Base) =>  class extends Base {    randomize() {}  };

Класс, использующий такие mix-ins, можно описать следующим образом:

js
class Foo {}class Bar extends calculatorMixin(randomizerMixin(Foo)) {}

Спецификации

Specification
ECMAScript® 2026 Language Specification
# sec-class-definitions

Совместимость с браузерами

Повторное определение класа

Класс не может быть переопределён. Попытка этого приведёт кSyntaxError .

Если мы запускаете код в веб браузере, к примеру в Firefox Web Console (Tools >Web Developer >Web Console) и вы используете ('Run') определение класса с одним и тем же именем дважды, вы получитеSyntaxError: redeclaration of let ClassName;. (Обсуждение по ошибке можно посмотреть вFirefox bug 1428672.) Chrome Developer Tools возвращает сообщение типаUncaught SyntaxError: Identifier 'ClassName' has already been declared at <anonymous>:1:1.

Смотрите также

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp