Как уже отмечалось выше, JavaScript это язык программирования, основанный на объектах.
Все объекты, доступные сценарию на языке JavaScript, подразделяются на три группы:
- встроенные объекты исполняющей системы;
- объекты среды, в которой исполняется сценарий (т. е. либо объекты клиента,
либо объекты сервера);
- пользовательские объекты, создаваемые сценарием в процессе его выполнения.
Объект JavaScript это неупорядоченный набор свойств. Свойство,
являющееся функцией, называется методом. Для доступа к свойству объекта используется
синтаксис:
имя_объекта.имя_свойства
Если название свойства задано текстовой строкой, то доступ к свойству возможен и так:
имя_объекта["имя_свойства"]
Этот синтаксис используется оператором итерации for
in.
Каждое свойство состоит из названия, значения и набора следующих атрибутов:
| Атрибут |
Описание |
| DontEnum |
Свойство не должно попадать в перечисление при итерации объекта оператором for
in. |
| DontDelete |
Попытка программно удалить данное свойство будет проигнорирована. См. описание операции
delete. |
| ReadOnly |
Неизменяемое свойство. Попытка программно изменить данное свойство будет проигнорирована.
(Отметим, что в некоторых случаях значение свойства с этим атрибутом может быть изменено
через внешнюю среду.) |
Новое свойство объекта создается просто присваиванием ему значения. Пусть, например, мы уже
создали объект myBrowser, который должен описывать наш Веб-обозреватель. Это описание
будет состоять из названия обозревателя (name) и его версии (version). Для
создания указанных свойств мы должны включить в сценарий следующие строки:
myBrowser.name = "Microsoft Internet Explorer";
myBrowser.version = "5.5";
У таких свойств, созданным пользователем, все перечисленные выше атрибуты сброшены в false.
В дальнейшем мы можем изменять значения этих свойств или извлекать их, например:
document.write(myBrowser.name, myBrowser.version);
Существует два способа создания новых объектов в JavaScript, а именно:
- Использование инициализатора объекта.
- Использование конструктора объектов.
Этот способ позволяет одновременно создать объект и присвоить значения всем или части его свойств.
Он применяется в тех случаях, когда мы создаем объект с уникальным набором свойств. Инициализатор
объекта имеет вид:
{свойство:значение [,свойство:значение]?}
Здесь свойство идентификатор, задающий имя свойства, а значение
выражение, задающее значение этого свойства.
Например, объект myBrowser из предыдущего примера может быть создан так:
var myBrowser = {name: "Microsoft Internet Explorer", version: "5.5"};
Усложним этот пример, добавив еще одно свойство объекта myBrowser, которое называется
options (опции обозревателя) и само является объектом:
var myBrowser = {name: "Microsoft Internet Explorer", version: "5.5",
options: {enableJava: true, enableCookies: false}};
Этот способ применяется в тех случаях, когда мы хотим создать класс объектов с определенным
набором свойств, а затем создавать новые объекты, просто указывая, к какому классу они должны
принадлежать. Для этого нужно сначала создать конструктор объектов, который является
функцией специального вида, а именно:
- имя функции задает имя создаваемого класса объектов;
- тело функции должно содержать присваивание начальных значений свойствам и методам создаваемого
объекта.
Например, конструктор для класса объектов Browser из предыдущего примера может
иметь следующий вид:
function Browser(name, version) {
this.name = name;
this.version = version;
}
Обратите внимание на использование операции this для
доступа к свойствам объекта.
Теперь для создания новых объектов класса Browser достаточно вызвать этот
конструктор в операции new, например:
var myBrowser = new Browser("Microsoft Internet Explorer", "5.5");
Вспомним теперь, что выше мы добавили свойство options объекта Browser,
которое само является объектом. Перепишем приведенный пример с учетом этого свойства:
function Options(enableJava, enableCookies) {
this.enableJava = enableJava;
this.enableCookies = enableCookies;
}
function Browser(name, version) {
this.name = name;
this.version = version;
this.options = options;
}
var myOptions = new Options(true, false);
var myBrowser = new Browser("Microsoft Internet Explorer", "5.5", myOptions);
Для доступа к свойствам свойства options используется нотация myBrowser.options.enableJava.
Поскольку методы являются разновидностью свойств, они создаются так же, как описано выше. Например,
мы можем добавить к конструктору объектов Browser метод aboutBrowser,
который будет выводить на экран обозревателя информацию о свойствах этого объекта:
function showBrowser() {
document.write("Обозреватель: " + this.name + " " + this.version);
}
function Browser(name, version) {
this.name = name;
this.version = version;
this.aboutBrowser = showBrowser;
}
В дальнейшем мы можем вызвать этот метод так: myBrowser.aboutBrowser().
При желании конструктор можно записать и короче, используя вложенное определение функции:
function Browser(name, version) {
this.name = name;
this.version = version;
this.aboutBrowser = function() {
document.write("Обозреватель: " + this.name + " " + this.version);
}
}
Допустим, что мы хотим в процессе выполнения сценария добавить новое свойство security
(безопасность) классу объектов Options (подчеркнем еще раз классу
объектов, а не отдельному его представителю myOptions). Для этого используется свойство
prototype объекта Function:
Options.prototype.security = null;
Теперь мы можем присвоить значение новому свойству объекта:
myBrowser.options.security = "Высокая";
Для удаления свойств объектов используется операция delete,
например:
delete Options.prototype.security;
JavaScript позволяет нам задать новый прототип для класса пользовательских объектов (прототипы встроенных
объектов доступны только для чтения). Рассмотрим такой пример:
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.area = function() {
return Math.PI * this.radius * this.radius;
}
function FullCircle(x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
FullCircle.prototype = Circle.prototype;
var myCircle = new FullCircle(0, 0, 1);
document.write(myCircle.area());
В этом примере сначала определяется класс объектов Circle со свойством radius и
методом area, возвращающим площадь круга. Затем определяется класс FullCircle,
конструктор которого дополнительно содержит координаты центра окружности. Затем указывается, что он наследует
прототип класс Circle. После этого мы создаем объект myCircle и вызываем его метод
area, который он унаследовал от прототипа класса Circle.
Мы можем удалить ранее созданный объект с помощью операции delete,
например:
delete myBrowser;
Чтение этого раздела не обязательно для того, чтобы научиться писать сценарии на языке JavaScript.
Его назначение состоит в том, чтобы дать представление о внутренних механизмах реализации JavaScript
тем программистам, которые имеют опыт работы с другими объектно-ориентированными языками программирования.
Если эти детали Вас не интересуют, то можете перейти к следующему разделу.
Большинство объектно-ориентированных языков (например, Java и C++) основаны на двух базовых
понятиях: классы объектов и экземпляры (instances) объектов.
- Класс объектов это абстрактное понятие, описывающее все свойства данного
класса (в Java эти свойства называются полями и методами, а в C++ членами класса, но суть
от этого не меняется).
- Экземпляр объекта это реализация класса, т. е. конкретный объект,
наделенный всеми свойствами данного класса.
JavaScript, в отличие от этих языков, основан на прототипах и не проводит различия между двумя
приведенными понятиями: в нем есть только объекты. Некоторым аналогом класса здесь выступает
прототип объекта, который определяет начальный набор свойств нового объекта. В процессе
выполнения программы объект может получать новые свойства; более того, он может сам выступать
в качестве прототипа при создании новых объектов.
В языках, основанных на классах, класс объектов описывается отдельной декларацией класса. В
этой декларации мы можем указать специальные методы, называемые конструкторами, которые
создают экземпляры данного класса. Конструктор выделяет память для экземпляра, инициализирует
значения его свойств и выполняет другие необходимые действия. После написания декларации класса
мы можем создавать его экземпляры путем вызова операции new имя_конструктора(...).
Создание объектов в JavaScript происходит примерно так же, но здесь декларация конструктора
совпадает с декларацией класса. Иными словами, мы определяем конструктор как функцию, которая
создает объекты с заданным начальным набором свойств и их значений. Затем мы так же создаем
объекты вызовом операции new имя_конструктора(...).
В языках, основанных на классах, классы объектов образуют иерархию классов, в которой
каждый класс может быть потомком какого-либо ранее определенного класса. Потомок класса наследует
все его свойства, но может иметь дополнительные собственные свойства или изменять свойства своего
предка. При этом набор свойств данного класса зафиксирован в его декларации и не может быть
изменен в ходе выполнения программы. Можно сказать, что здесь текущее состояние реализуется
экземплярами классов, методы реализуются классами, а наследование структурой и поведением.
JavaScript поддерживает наследование, основанное на прототипах. С каждым конструктором связан
соответствующий прототип объекта, и каждый объект, созданный конструктором, содержит неявную
ссылку на этот прототип. Прототип, в свою очередь, может содержать ссылку на свой прототип и
так далее. Так образуется цепочка прототипов. Ссылка на свойство объекта
это ссылка на первый прототип в цепочке прототипов объекта, который содержит свойство с данным
именем. Иными словами, если данный объект имеет свойство с данным именем, то используется ссылка
на это свойство; если нет, то исследуется прототип этого объекта и т. д.
В JavaScript текущее состояние и методы реализуются объектами, а структура и поведение наследуются.
Все объекты, которое явно содержат свойство, которое содержит их прототип, разделяют это свойство
и его значение. В отличие от языков, основанных на классах, свойства могут динамически добавляться
к объектам и динамически удаляться. В частности, конструкторы не обязаны присваивать значения
всем или некоторым свойствам создаваемого объекта.
Перечисленные в этом разделе отличия объектной модели JavaScript от языков, основанных на классах,
сведены в следующей таблице.
Таблица 8. Объектная модель JavaScript
Модель, основанная на классах
(Java и C++) |
Модель, основанная на прототипах (JavaScript) |
| Класс объектов и экземпляр объекта это различные понятия. |
Все объекты являются экземплярами объектов. |
| Класс определяется декларацией класса. Экземпляр класса создается конструктором. |
Набор объектов определяется и создается функцией-конструктором. |
| Новый объект создается операцией new. |
Новый объект создается операцией new. |
| Существует иерархия классов, в которой новые классы являются потомками ранее определенных. |
Существует иерархия объектов, в которой объект имеет прототип, заданной функцией-конструктором. |
| Свойства наследуются по цепочке классов-потомков. |
Свойства наследуются по цепочке прототипов. |
| Декларация класса определяет все свойства всех экземпляров данного класса. Набор
свойств не может динамически изменяться в ходе выполнения программы. |
Конструктор или прототип определяют начальный набор свойств. Свойства набора
объектов или отдельного объекта могут динамически добавляться и удаляться в ходе выполнения
программы. |