- Объектные литералы
Объектно-ориентированный JavaScript
Jonathan Snook, 15 сентября 2007
Когда я только начинал программировать на JavaScript, я старался всю пригодную к повторному использованию функциональность инкапсулировать в функции. Но по мере усложнения задач и изучения мной объектно-ориентированного программирования в других языках, мне захотелось применять в JavaScript что-то подобное.
В объектно-ориентированном программировании объект воспринимается как предмет, это может быть изображение, пользователь, документ, все, что можно описать существительным. У объекта есть свойства и методы, первые тоже можно описать существительными, они отражают состояние объекта, вторые можно описать глаголами они отражают действия, которые может выполнять объект. К примеру, array в JavaScript это объект, он содержит свойства, такие как length, которые содержат информацию об объекте и методы, такие как push, которые позволяют выполнять с объектом какие-то действия.
Основная идея заключается в том, что объекты инкапсулируют всю связанную с ними функциональность.
В JavaScript мы часто выполняем похожие задачи. В качестве примера можно взять, валидацию форм, когда пользователь подтверждает форму, нужно проверить, все ли обязательные поля заполнены, соответствуют ли стандартам адреса электронной почты и номера телефонов и, возможно, некоторые специфические поля. Почему бы, вместо создания нескольких функций не объединить, эту функциональность в одном объекте FormValidator
, который можно легко использовать и на других сайтах. В дополнение ко всему, объекты позволяют уменьшить загрязнение глобального пространства имен, тем самым сделать код чище.
JavaScript очень гибкий язык, он предоставляет два основных метода создания объектов:
§ использование объектного литерала,
§ использование ключевого слова new
.
У каждого из них есть свои особенности, преимущества и недостатки, которые я попытаюсь раскрыть в этой статье.
Использование объектного литерала
Создание объекта с помощью объектного литерала, достаточно очевидно. Объектный литерал представляет из себя, заключенные в фигурные скобки, пары свойств и их значений, разделенные запятыми. В свою очередь каждое свойство отделено от его значения с помощью двоеточия. Имена свойств могут быть идентификаторами, строками или числами, а значения могут быть строками, числами, функциями или другими объектами. Имена свойств преобразуются в строки, это значит что строка "25"
и число 25
, указывают на одно и тоже свойство, и при использовании в одном объекте будут переназначать друг друга.
Пример:
{ property: value, property: value }
Создание объектов
Для демонстрации этого метода, давайте создадим простой объект с тремя свойствами, два из них будут хранить числа, тогда как третье будет анонимной функцией (функцией без имени):
var AnimationManager = { framesPerSecond: 30, totalLength: 15, startAnimation: function() { /* code */ } }
Стоит обратить внимание на то, что объектный литерал, это всего лишь сокращенный способ создания объектов с помощью встроенного типа Object
, а вышеприведенный пример можно переписать так:
var AnimationManager = new Object(); AnimationManager.framesPerSecond = 30; AnimationManager.totalLength = 15; AnimationManager.startAnimation = function () { /* code */ };
Доступ к свойствам объекта
Мы создали объект AnimationManager
и теперь можем получить доступ к его свойствам с помощью точки или квадратных скобок, следующие две строки кода дают один и тот же результат:
alert(AnimationManager.framesPerSecond); // object.property alert(AnimationManager['framesPerSecond']); // object['property']
Чаще для доступа к свойствам мы будем использовать точку, но возможность доступа к объекту как к хеш таблице может быть полезна, если нужен гибкий доступ к нескольким похожим свойствам. К примеру, нам может понадобиться функция, устанавливающая свойства framesPerSecond
и totalLength
, используя только точку, мы будем вынуждены обратиться к такому коду:
function changeValue(property, value) { if (property == "framesPerSecond") { AnimationManager.framesPerSecond = value; } else { AnimationManager.totalLength = value; } }
А, зная о том, что к свойствам можно обращаться с помощью квадратных скобок, мы получим более компактный код:
function changeValue(property, value) { AnimationManager[property] = value; }
Добавляем свойства или методы
В процессе работы с объектом мы можем, создать новые свойства или методы в любой момент. Создать новое свойство и присвоить ему значение, так же просто, как и присвоить значение существующему:
AnimationManager.stopAnimation = function() { } AnimationManager.defaultTween = "sinoidal";
Использование функций
В JavaScript функция является объектом и может быть использована в качестве шаблона для новых объектов.
В предыдущей главе, создавая AnimationManager
, нам не нужно было заботиться о механизме создания нескольких таких объектов, поэтому объектный литерал был отличным выбором. Используя функцию объект, мы получаем возможность создать своеобразный чертеж объекта, по которому можно будет воспроизводить его снова и снова.
Давайте расширим предыдущий пример с AnimationManager
, и дадим ему возможность контролировать множество объектов Animation
. Если бы мы решили определить Animation с помощью объектного литерала, нам пришлось бы копировать один и тот же код для создания каждого анимированного объекта, куда удобней создавать объекты Animation из одного шаблона.
Используем шаблон
С помощью ключевого слова new
и функции шаблона, мы можем создать объект с одними и теми же свойствами столько раз, сколько нам необходимо:
function Animation(element) { this.animationLength = 30; this.element = element; } var obj = document.getElementById('login'); var animateLogin = new Animation(obj);
При выполнении new Animation(obj)
создается пустой объект, а потом выполняется функция Animation,
которая может ссылаться на этот объект с помощью ключевого слова this
, что позволяет нам создать необходимые свойства этого объекта. После выполнения строки var animateLogin = new Animation(obj);
переменная animateLogin
будет ссылаться на объект Animation
, а его свойствам animationLength
и element
будут присвоены соответствующие значения.
Мы можем создать и методы, просто присваивая свойствам объекта функции:
function Animation(element) { this.animationLength = 30; this.element = element; this.onStart = function () { alert("The animation is starting!"); }; this.onEnd = function () { alert("The animation is ending!"); }; } var obj = document.getElementById('login'); var animateLogin = new Animation(obj);
Обратите внимание, что можно добавить свойства к самой функции Animation
:
function Animation() { } Animation.animationLength = 30; Animation.element = element;
Разница в том, что в таком случае они не будут частью шаблона. Если мы выполним new Animation()
после приведенного выше кода, то получим пустой объект, вместо объекта с двумя свойствами:
var animateLogin = new Animation(loginform); Animation.animationLength = 30; alert(animateLogin.element); alert(animateLogin.animationLength); // undefined!