Объектная модель JavaScript
Чтение этого раздела не обязательно для того, чтобы научиться писать сценарии на языке JavaScript. Его назначение состоит в том, чтобы дать представление о внутренних механизмах реализации JavaScript тем программистам, которые имеют опыт работы с другими объектно-ориентированными языками программирования. Если эти детали Вас не интересуют, то можете перейти к следующему разделу.
Прототипы объектов
Большинство объектно-ориентированных языков (например, Java и C++) основаны на двух базовых понятиях: классы объектов и экземпляры (instances) объектов.
Класс объектов - это абстрактное понятие, описывающее все свойства данного класса (в Java эти свойства называются полями и методами, а в C++ членами класса, но суть от этого не меняется).
Экземпляр объекта - это реализация класса, т. е. конкретный объект, наделенный всеми свойствами данного класса.
JavaScript, в отличие от этих языков, основан на прототипах и не проводит различия между двумя приведенными понятиями: в нем есть только объекты. Некоторым аналогом класса здесь выступает прототип объекта, который определяет начальный набор свойств нового объекта. В процессе выполнения программы объект может получать новые свойства; более того, он может сам выступать в качестве прототипа при создании новых объектов.
Создание объектов
В языках, основанных на классах, класс объектов описывается отдельной декларацией класса. В этой декларации мы можем указать специальные методы, называемые конструкторами, которые создают экземпляры данного класса. Конструктор выделяет память для экземпляра, инициализирует значения его свойств и выполняет другие необходимые действия. После написания декларации класса мы можем создавать его экземпляры путем вызова операции new имя_конструктора(...).
Создание объектов в JavaScript происходит примерно так же, но здесь декларация конструктора совпадает с декларацией класса. Иными словами, мы определяем конструктор как функцию, которая создает объекты с заданным начальным набором свойств и их значений. Затем мы так же создаем объекты вызовом операции new имя_конструктора(...).
Наследование
В языках, основанных на классах, классы объектов образуют иерархию классов, в которой каждый класс может быть потомком какого-либо ранее определенного класса. Потомок класса наследует все его свойства, но может иметь дополнительные собственные свойства или изменять свойства своего предка. При этом набор свойств данного класса зафиксирован в его декларации и не может быть изменен в ходе выполнения программы. Можно сказать, что здесь текущее состояние реализуется экземплярами классов, методы реализуются классами, а наследование - структурой и поведением.
JavaScript поддерживает наследование, основанное на прототипах. С каждым конструктором связан соответствующий прототип объекта, и каждый объект, созданный конструктором, содержит неявную ссылку на этот прототип. Прототип, в свою очередь, может содержать ссылку на свой прототип и так далее. Так образуется цепочка прототипов. Ссылка на свойство объекта - это ссылка на первый прототип в цепочке прототипов объекта, который содержит свойство с данным именем. Иными словами, если данный объект имеет свойство с данным именем, то используется ссылка на это свойство; если нет, то исследуется прототип этого объекта и т. д.
В JavaScript текущее состояние и методы реализуются объектами, а структура и поведение наследуются. Все объекты, которое явно содержат свойство, которое содержит их прототип, разделяют это свойство и его значение. В отличие от языков, основанных на классах, свойства могут динамически добавляться к объектам и динамически удаляться. В частности, конструкторы не обязаны присваивать значения всем или некоторым свойствам создаваемого объекта.
Резюме
Перечисленные в этом разделе отличия объектной модели JavaScript от языков, основанных на классах, сведены в следующей таблице.
Объектная модель JavaScriptМодель, основанная на классах (Java и C++) | Модель, основанная на прототипах (JavaScript) |
---|
Класс объектов и экземпляр объекта - это различные понятия. | Все объекты являются экземплярами объектов. | Класс определяется декларацией класса. Экземпляр класса создается конструктором. | Набор объектов определяется и создается функцией-конструктором. | Новый объект создается операцией new. | Новый объект создается операцией new. | Существует иерархия классов, в которой новые классы являются потомками ранее определенных. | Существует иерархия объектов, в которой объект имеет прототип, заданной функцией-конструктором. | Свойства наследуются по цепочке классов-потомков. | Свойства наследуются по цепочке прототипов. | Декларация класса определяет все свойства всех экземпляров данного класса. Набор свойств не может динамически изменяться в ходе выполнения программы. | Конструктор или прототип определяют начальный набор свойств. Свойства набора объектов или отдельного объекта могут динамически добавляться и удаляться в ходе выполнения программы. | 1 2
8 8 8
| |