JavaScript — это язык на базе прототипов, и каждый объект JavaScript имеет скрытое внутреннее свойство [[Prototype]]
, которое можно использовать для расширения свойств и методов объекта. Вы можете узнать больше о прототипах из нашего обучающего модуля Понимание принципов прототипов и наследования в JavaScript.
До недавнего времени промышленные разработчики использовали функции конструктора для имитации объектно-ориентированного шаблона в JavaScript. Языковая спецификация ECMAScript 2015 (часто называемая ES6) ввела в язык JavaScript понятие классов. Классы в JavaScript не добавляют дополнительные функции, и представляют собой способ упростить синтаксис при использовании прототипов и наследования и сделать его более элегантным. Поскольку в других языках программирования также используются классы, синтаксис классов в JavaScript упрощает работу для разработчиков, владеющих другими языками.
Класс JavaScript — это вид функции. Для декларирования классов используется ключевое слово class
. Мы используем синтаксис выражения функции для инициализации функции и синтаксис выражения класса для инициализации класса.
Мы можем получить доступ к [[Prototype]]
объекта с помощью метода Object.getPrototypeOf()
. Давайте протестируем созданную нами пустую функцию.
Outputƒ () { [native code] }
Также мы можем использовать этот метод для только что созданного нами класса.
Outputƒ () { [native code] }
Программный код, декларированный с помощью function
и class
, возвращает функцию [[Prototype]]
. При использовании прототипов любую функцию можно превратить в экземпляр конструктора с помощью ключевого слова new
.
Outputx {}
constructor: ƒ ()
Это также относится и к классам.
Outputy {}
constructor: class
Эти примеры конструктора прототипов пустые, но вы видите, как оба метода позволяют добиться одинакового результата вне зависимости от синтаксиса.
В обучающем модуле Прототипы и наследование мы создали пример, основанный на создании персонажа в текстовой ролевой игре. На этом же примере мы рассмотрим, как обновлять синтаксис от функций к классам.
Функция конструктора инициализируется с рядом параметров, которые назначаются как свойства this,
относящиеся к самой функции. Согласно правилам, первая буква идентификатора будет преобразована в заглавную.
При трансляции в синтаксис класса, как показано ниже, структура будет очень похожей.
Мы знаем, что функция конструктора является планом объекта благодаря тому, что первая буква инициализатора (необязательно) заглавная, и потому что мы знакомы с синтаксисом. Ключевое слово class
показывает назначение нашей функции более прямо.
Единственная разница в синтаксисе инициализации заключается в использовании ключевого слова class
вместо function
, и в том, что свойства назначаются внутри метода constructor()
.
При использовании функций конструктора методы обычно назначаются непосредственно в prototype
вместо инициализации, как показано ниже на примере метода greet()
.
При использовании классов этот синтаксис упрощается, и метод можно добавить напрямую в класс. Благодаря концепции заблаговременного определения методов, введенной в ES6, определение методов стало еще более быстрой процедурой.
Давайте посмотрим на эти свойства и методы в действии. Мы создадим новый экземпляр Hero
, используя ключевое слово new
, и присвоим некоторые значения.
Если мы распечатаем дополнительную информацию о нашем новом объекте с помощью команды console.log(hero1)
, мы более подробно увидим. что происходит при инициализации класса.
OutputHero {name: "Varg", level: 1}
__proto__:
▶ constructor: class Hero
▶ greet: ƒ greet()
В результатах мы видим, что функции constructor()
и greet() functions
были применены к прототипу __proto__
или [[Prototype]]
объекта hero1
, а непосредственно к объекту hero1
как к методу. Хотя при создании функций конструктора это очевидно, при создании классов дело обстоит по другому. Классы позволяют использовать более простой и сжатый синтаксис, но при этом немного теряется понятность процесса.
Функции конструктора и классы можно расширять на новые планы объекта на основе родительского экземпляра. Это позволяет не повторять код для похожих объектов, для которых нужно просто добавить дополнительные или более детальные характеристики.
Новые функции конструктора можно создавать на основе родительского экземпляра с помощью метода call()
. В примере ниже мы создадим более конкретный класс персонажа Mage
и присвоим ему свойства Hero
с помощью метода call()
, а также добавим дополнительное свойство.
Сейчас мы можем создать новый экземпляр Mage
, используя те же свойства, что и Hero
,а также добавленное свойство.
Отправив на консоль команду hero2
, мы увидим, что создали новый экземпляр Mage
на базе конструктора.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__:
▶ constructor: ƒ Mage(name, level, spell)
Для классов ES6 ключевое слово super
используется вместо call
для доступа к родительским функциям. Мы будем использовать extends
для обозначения родительского класса.
Теперь мы можем точно так же создать новый экземпляр Mage
.
Распечатаем hero2
на консоли и посмотрим результат.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__: Hero
▶ constructor: class Mage
Результат практически такой же, но в конструкции класса прототип [[Prototype]]
связан с родительским объектом, в данном случае Hero
.
Ниже приводится полное сравнение процесса инициализации, добавления методов и наследования между функцией конструктора и классом.
Хотя синтаксис различается, конечный результат для обоих методов практически одинаковый. Классы дают более краткий способ создания шаблонов объектов, а функции конструктора более точно описывают конкретную механику.
В этом обучающем модуле мы узнали о сходствах и различиях между функциями конструктора JavaScript и классами ES6. Классы и конструкторы имитируют объектно-ориентированную модель наследования в JavaScript, который представляет собой язык наследования на основе прототипов.
Понимание принципов наследования прототипов очень важно, если вы хотите стать эффективным разработчиком на JavaScript. Знакомство с классами очень полезно, потому что популярные библиотеки JavaScript, такие как React, часто используют синтаксис class
.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!