Custom objects
Класс
JavaScript — это прототипно-ориентированный язык, и в нем нет оператораclass
, который имеет место в C++ или Java. Иногда это сбивает с толку программистов, привыкших к языкам с операторомclass
. Вместо этого JavaScript использует функции как конструкторы классов (В es6 появилось ключевое слово class для упрощения описания конструкторов). Объявить класс так же просто, как объявить функцию. В примере ниже мы объявляем новый класс Person с пустым конструктором:
Объект (экземпляр класса)
Для создания нового экземпляра объекта obj
мы используем оператор new obj
, присваивая результат (который имеет типobj
) в переменную.
В примере выше мы определили классPerson
. В примере ниже мы создаем два его экземпляра (person1
иperson2
).
Конструктор
Конструктор вызывается в момент создания экземпляра класса (в тот самый момент, когда создается объект). Конструктор является методом класса. В JavaScript функция служит конструктором объекта, поэтому нет необходимости явно определять метод конструктора. Любое действие, определенное в классе, будет выполнено в момент создания экземпляра класса.
Конструктор используется для задания свойств объекту или для вызова методов, которые подготовят объект к использованию. Добавление методов и их описаний производится с использованием другого синтаксиса, описанного далее в этой статье.
В примере ниже, конструктор класса Person
выводит в консоль сообщение в момент создания нового экземпляра Person
.
Свойство (атрибут объекта)
Свойства — это переменные, содержащиеся в классе; каждый экземпляр объекта имеет эти свойства. Свойства устанавливаются в конструкторе (функции) класса, таким образом они создаются для каждого экземпляра.
Ключевое словоthis
, которое ссылается на текущий объект, позволяет вам работать со свойствами класса. Доступ (чтение и запись) к свойствам снаружи класса осуществляется синтаксисом InstanceName.Property,
так же как в C++, Java и некоторых других языках. (Внутри класса, для получения и изменения значений свойств, используется синтаксисthis.Property
)
В примере ниже мы определяем свойство firstName
для класса Person
при создании экземпляра:
Методы
Методы — это функции (и определяются как функции), но с другой стороны следуют той же логике, что и свойства. Вызов метода похож на доступ к свойству, но вы добавляете () на конце имени метода, возможно, с аргументами. Чтобы объявить метод, присвойте функцию в именованное свойство prototype
класса. Потом вы сможете вызвать метод объекта под тем именем, которое вы присвоили функции.
В примере ниже мы определяем и используем методsayHello()
для классаPerson
.
В JavaScript методы это — обычные объекты функций, связанные с объектом как свойства: это означает, что вы можете вызывать методы "вне контекста". Рассмотрим следующий пример:
Как показывает пример, все ссылки, которые мы имеем на функцию sayHello
— person1
,Person.prototype
, переменнаяhelloFunction
и т.д. — ссылаются на одну и ту же функцию. Значениеthis
в момент вызова функции зависит от того, как мы ее вызываем. Наиболее часто мы обращаемся кthis
в выражениях, где мы получаем функцию из свойства объекта —person1.sayHello()
—this
устанавливается на объект, из которого мы получили функцию (person1
), вот почемуperson1.sayHello()
использует имя "Alice", аperson2.sayHello()
использует имя "Bob". Но если вызов будет совершен иначе, тоthis
будет иным: вызовthis
из переменной —helloFunction()
— установитthis
на глобальный объект (window
в браузерах). Так как этот объект, вероятно, не имеет свойстваfirstName
, функция выведет "Hello, I'm undefined" (так произойдет в нестрогом режиме; в strict mode всё будет иначе (ошибка), не будем сейчас вдаваться в подробности, чтобы избежать путаницы). Или мы можем указатьthis
явно с помощьюFunction#call
(илиFunction#apply
) как показано в конце примера.
Наследование
Наследование — это способ создать класс как специализированную версию одного или нескольких классов (JavaScript поддерживает только одиночное наследование). Специализированный класс, как правило, называют потомком, а другой класс — родителем. В JavaScript наследование осуществляется присвоением экземпляра класса родителя классу потомку. В современных браузерах вы можете реализовать наследование с помощью Object.create.
В примере ниже мы определяем классStudent
как потомок классаPerson
. Потом мы переопределяем методsayHello()
и добавляем методaddGoodBye()
Относительно строки Student.prototype = Object.create(Person.prototype);.
В старых движках JavaScript, в которых нет Object.create
, можно использовать полифилл (ещё известный как "shim") или функцию, которая достигает тех же результатов, таких как:
Инкапсуляция
В примере выше классу Student
нет необходимости знать о реализации методаwalk()
классаPerson
, но он может его использовать; КлассStudent
не должен явно определять этот метод, пока мы не хотим его изменить. Это называется инкапсуляция, благодаря чему каждый класс собирает данные и методы в одном блоке.
Сокрытие информации — распространённая особенность, часто реализуемая в других языках программирования как приватные и защищённые методы/свойства. Однако в JavaScript можно лишь имитировать нечто подобное, это не является необходимым требованием объектно-ориентированного программирования.
Полиморфизм
Так как все методы и свойства определяются внутри свойстваprototype
, различные классы могут определять методы с одинаковыми именами; методы находятся в области видимости класса, в котором они определены, пока два класса не имеют связи родитель-потомок (например, один наследуется от другого в цепочке наследований).
Last updated