Объектно-ориентированное программирование в JavaScriptВ этой статье я расскажу об объектной модели JavaScript и о техниках, которые можно использовать для реализации базовых ООП-концепций.
Объекты в JavaScriptВ первую очередь нужно сказать, что JavaScript – это объектный язык. Это значит, что понятием класса (в привычном понимании этого слова) он не оперирует, но оперирует понятием объекта. Приведу пример:
Говоря об объекте, можно провести аналогию с хэшем: объект, как и хэш, является набором ключей (атрибутов) и соответствующих им значений. JavaScript даже поддерживает альтернативный синтаксис для доступа к атрибутам объекта – например, последние 2 строки предыдущего примера можно было записать так:
greeter[‘name’] = ‘Mike Lapshin’; greeter[‘greet’]();
Доступ к атрибутам по строке дает программисту дополнительные возможности. Например, мы можем изменить значение атрибута, имя которого находится в строковой переменной: var attrName = ‘name’; greeter[attrName] = ‘Alex’; При присвоении значения несуществующему атрибуту этот атрибут будет автоматически создан:
greeter. newAttribute = ‘New attribute value’; alert(greeter. newAttribute); КонструкторыДля создания объектов в JavaScript, как и в других языках, существуют конструкторы. Конструктор в JavaScript – это глобальная функция, вызываемая с помощью оператора new. Внутри этой функции программист может инициализировать атрибуты объекта, обращаясь к ним через ключевое слово this:
Так как метод является равноправным атрибутом объекта, мы можем извне заменить его на какой-либо другой:
Конечно, подобное изменение логики объекта за его пределами не корректно с точки зрения ООП, но сейчас мы не будем обращать на это внимание, так как этот пример нам нужен для другой цели.
Мы видим, что метод greet() объекта alexGreeter остался неизменным - что, по-сути, логично. Дело в том, что если метод инициализируется в конструкторе, то при создании объекта он каждый раз будет создаваться заново (то есть копироваться). Обратная сторона медали в этом случае – память. Если создать 20000 объектов Greeter, то абсолютно одинаковый у всех экземпляров метод Greeter. greet() будет создан в памяти 20000 раз.
ООП же подразумевает, что экземпляры одного и того же класса различаются только данными, а программная логика у них идентична. Соответственно, такое дублирование методов – неоправданная трата ресурсов.
Прототип объектаДля решения этой проблемы в JavaScript существует специальное средство, называемое прототипом. Метод, инициализированный в прототипе, создается только один раз и разделяется между всеми объектами, использующими этот прототип. Таким образом, наш пример можно переписать следующим образом:
Прототип, как и все остальное в JavaScript, является объектом. Доступ к нему можно получить через ИмяКласса. prototype. Мы можем переписать 6-ю строку примера следующим образом:
Greeter. prototype[‘greet’] = function() { И это будет работать. Вообще, нужно объяснить принцип взаимодействия объекта с его прототипом. Когда интерпретатор JavaScript встречает обращение к атрибуту объекта (через this внутри класса или через переменную извне), он сперва проверяет, определен ли этот атрибут в самом объекте. Если запрашиваемый атрибут определен, используется его значение. В противном случае атрибут ищется в прототипе объекта. Если атрибут не найден и там, то он считается неопределенным.
На самом деле атрибута greet нет ни у объекта alexGreeter, ни у объекта johnGreeter. У этих объектов есть только атрибут name. Но интерпретатор при обращении к методу greet находит этот метод в прототипе.
Чтобы проиллюстрировать вышесказаное, попробуем еще раз переопределить метод greet. Сперва мы переопределим его у конкретного объекта, а потом у прототипа объекта.
alexGreeter. greet = function() { alert(‘Howdy, ‘ + this. name); }
// Теперь у объекта alexGreeter // есть атрибут greet, и интерпретатор // при обращении к нему будет использовать // атрибут объекта, а не атрибут прототипа alexGreeter. greet(); // Howdy, Alex
// У объекта johnGreeter атрибута greet // нет, поэтому будет использована общая версия // этого метода из прототипа класса Greeter johnGreeter. greet(); // Hello, John Но если переопределить метод greet в прототипе, а сами объекты оставить неизменными, новый метод распространятся сразу на все объекты:
Нужно отметить, что добавление в уже существующие объекты новой функциональности всегда осуществляется посредством изменения их прототипа. Например, такой подход реализован в библиотеке Prototype, которая расширяет (в тех браузерах, которые это поддерживают) функциональность стандартных объектов (строк, массивов, DOM-элементов) с помощью изменения их прототипа. Вернутся Вам будет интересно:
|
- Публикации
Итак, у вас имеется свой собственный форум, но его никто не посещает? Мы готовы помочь вам справиться с этой нелегкой проблемой.
Данная статья в основном рассчитана на тех, кто самостоятельно занимается продвижением своего проекта.
Проклял все настройки кодировок, проклял DirectAdmin и еле-еле нашел то место где располагается и задается общий пароль для ...
Твиттер уже давно стал из нового web 2. 0 сервиса рекламной площадкой с огромным количеством потенциальных пользователей ...
Самое время кратко описать, чем нам придется заниматься. Прежде всего нужно понять, что блог ты будешь делать для получения ...
Долго не знал с чего начать данную статью. Статья что-то типа мыслей вслух и философии.