Манипулирование объектами

Для работы с объектами в JavaScript предназначены два оператора. С одним из них мы познакомились в примере 10 - цикл по свойствам объекта:

for( переменная_цикла in объект) { [операторы]}

Этот цикл осуществляет перебор всех свойств объекта. В переменной цикла на каждой итерации сохраняется название свойства объекта. Значение свойства объекта можно получить с помощью конструкции

объект[имя_свойства]

Количество итераций равно количеству перечисляемых свойств, существующих у заданного в заголовке цикла объекта.

Пример 2. Перечисление свойства объекта HTML
Для обеспечения возможности доступа в сценарии к элементу HTML отображаемого в браузере документа с помощью объекта в язык HTML была добавлена возможность идентификации любого элемента страницы с помощью атрибута id. Его значением является алфавитно-цифровой идентификатор, начинающийся с буквы. По этому имени в сценарии JavaScript можно получить ссылку на объект, соответствующий указанному элементу HTML. В Internet Explorer для этого достаточно указать это имя и автоматически ссылка будет получена. После чего можно получать или изменять значения свойств этого объекта, обычно соответствующих атрибутам элемента HTML, соответствующего этому объекту. Однако у всех объектов есть свойства, которые не соответствуют никаким атрибутам. Эти свойства реализованы в соответствии с используемой в браузере объектной моделью документа. В представленном ниже сценарии при щелчке на кнопке Свойства абзаца вызывается функция properties(), в которую передается ссылка на объект par1, соответствующий абзацу страницы HTML. Эта функция возвращает строку с названиями и значениями всех свойств объекта, соответствующего абзацу с атрибутом id=par1, которая отображается на странице HTML. <HEAD><SCRIPT LANGUAGE="JaVaSCRipt"><!--function properties(obj) { var result = "" for (var i in obj) { result += obj.id + "." + i + " = " + obj[i] + "<BR>" } result += "<HR>" return result}//--></SCRIPT></HEAD><BODY><p id="par1">Получить в сценарии доступ к объекту, соответствующемукакому-нибудь элементу HTML страницы, можно с помощьюзначений его атрибутов <b>id</b> или <b>name</b>.</p><input type=button value="Свойства абзаца" xnclick="document.write(properties(par1))"></BODY>

Второй оператор, предназначенный для работы с объектами, - оператор with, позволяющий задать объект по умолчанию для блока операторов, определенных в его теле. Это означает, что все встречаемые в операторах этого блока свойства и методы являются свойствами и методами указанного объекта. Применение этого оператора избавляет от необходимости указывать иерархию принадлежности объекта и сокращает исходный текст программы.

Текст приведенного выше сценария с использованием оператора with можно записать и так:

with( obj) { result += id + "." + i + " = " + [i] + "<BR>"}

Полезно использовать этот оператор для объекта Math. Тогда обращение к его свойствам и методам осуществляется без явного указания префикса Math. Например:

with(Math) {r = sin(2.0) // Вычисление синусаl = 2*PI*r // Вычисление длины окружности}

Обработка ошибок

При выполнении сценария могут возникать ошибки. Браузер Internet Explorer отображает их либо в диалоговом окне:

Рис. 1.

Это окно появляется тогда, когда в браузере установлен режим уведомления об ошибках сценария и запрещена их отладка на вкладке Дополнительно окна его свойств:

Рис. 2.

Если в этом окне сброшен флажок Запретить отладку сценариев, то появляется диалоговое окно следующего вида, предлагающее выполнить отладку сценария с помощью какой-либо специальной программы:

Рис. 3.

Если ответить Да, то браузер предложит в диалоговом окне Just-In-Time Debugging выбрать программу отладки:

Рис. 4.

Возможна ситуация, когда в сценарии потребуется перехватить непредвиденные ошибки, возникающие во время выполнения, дабы предотвратить появление диалогового окна об ошибке. Для этого в JavaScript имеется достаточно простой механизм, реализуемый оператором try...catch...finally:

try{// Код, в котором могут содержаться ошибки}catch(e){// Обработчик ошибки}finally{// всегда выполняемый код}

Код сценария с потенциальными ошибками заключается в блок try. Если при выполнении кода возникают ошибки, то диалоговое окно браузера не появляется, а управление передается блоку catch, в котором и обрабатываются все ошибки. Переменная е (произвольный идентификатор) в блоке catch будет содержать ссылку на объект Error, хранящий информацию об ошибке. Код блока finally выполняется всегда - возникла или не возникла ошибка.

У объекта Error имеется четыре свойства:

Свойство Описание
name Название ошибки (только чтение).
message Сообщение ошибки (только чтение).
description Описание ошибки.
number Содержит 32-битный код ошибки. Старшие два байта (для их выделения воспользуйтесь операцией e.number>>16 & 0x1FFF) содержат вспомогательный код, младшие (для их выделения воспользуйтесь операцией e.number & 0xFFFF) код ошибки.

 

Пример 3. Обработка ошибок
При загрузке следующей страницы сценарий отображает диалоговое окно с подтверждением распечатать свойства объекта-абзаца par1. Если пользователь отвечает Да, то возникает ошибка, так как к тому времени, когда в сценарии будет выполняться обращение к объекту par1, он еще не будет создан - тело документа к этому моменту еще не обработано. Оператор if сценария заключен в блок try. Поэтому управление будет передано в блок catch, в котором будут распечатаны свойства сгенерированного объекта Error - переменная e. При этом обязательно выполнится оператор блока finally. Если пользователь отвечает Нет, то ошибки не возникает, так как не будет обращения к объекту par1, операторы блока catch выполняться не будут, но блока finally выполнится обязательно. <script> reply = confirm("Распечатать содержимое абзаца par1?") try{ if(reply){ alert(par1.innerText); } }catch(e){ alert("Название ошибки: "+e.name + "\n"+ "Сообщение ошибки: "+e.message + "\n"+ "32-битный код ошибки: "+e.number+"\n"+ "Вспомогательный код ошибки: "+ (e.number>>16 & 0x1FFF) +"\n" + "Истинный код ошибки: "+ (e.number & 0xFFFF) +"\n" + "Описание ошибки: "+e.description) }finally{ alert("Код блока finally выполняется всегда!") }</script><body><p id=par1>Абзац с атрибутом id='par1'.</p></body>

Также возможна ситуация, когда не требуется немедленно обрабатывать ошибку, а передать ее на обработку в процедуру более высокого уровня. Для этого следует инициировать собственную ошибку, которая будет перехвачена на более высоком уровне или просто отображена для пользователя. Для инициирования ошибки используется оператор throw, единственным параметром которого является некоторое выражение. В этом случае можно задать строку с описанием ошибки или некоторый ее номер. Но более распространенным способом в этой ситуации является создание объекта Error, который передается оператору throw как параметр.

Пример 4. Генерирование ошибки
В этом сценарии функция add() (сложение двух чисел) проверяет количество переданных в нее параметров. Если фактических параметров меньше двух, то функция сама не обрабатывает эти ошибки в своем теле, а генерирует ошибку, передавая ее в код, вызывающий эту функцию, который ее и обрабатывает. <script>// Функция, генерирующая ошибкуfunction add(x,y){// Создание объекта Error var err = new Error() switch(arguments.length){ case 0:// Создание ошибки с кодом 800 err.number = 800 err.description = "Параметров должно быть два.";// Генерирование ошибки throw err break; case 1:// Создание ошибки с кодом 801 err.number = 801 err.description = "Не задан второй параметр.";// Генерирование ошибки throw err break; }// Возвращаемое значение функции return x+y;} // Обращение к функции add() с обработкой возможной ошибкиtry{// функция add() сгенерирует ошибку с номером 801 alert(add(5))}catch(e){ alert(e.description+"\n"+e.number)} </script>

 

Упражнение 1.  
Добавить метод propList() (пример 10) к прототипу объекта Object, а также добавить к прототипу этого же объекта свойство list со значением "Добавленное к прототипу Object". Проверить на объектах String, Date, Number, Function, Array, Boolean, действительно ли будут добавляться к экземплярам указанных объектов добавленные к прототипу объекта Object метод и свойство.

 

Упражнение 2.  
Добавить к прототипу объекта Array метод вычисления максимального элемента массива и посмотреть его работу на экземплярах объектов этого типа, содержащими только числовые элементы, только строковые и смешанные (числа и строки).

 

Упражнение 3.  
Создать массив, элементы которого хранят ссылки на все 6 типов встроенных объектов JavaScript. Случайным образом "перемешать" его элементы. После этого распечатать отчет о том, какие объекты хранятся в его элементах, начиная с первого.

 

Упражнение 4.  
Реализовать нижеприведенный сценарий. Проверить доступность свойств 0, 1, 2, 3 массива. Объяснить результаты. Поэкспериментировать с другими типами встроенных объектов. var a = new Array("apple", "banana", "cactus"); a["q"] = 9document.write(a.propertyIsEnumerable("q"))

 

Упражнение 5.  
Отобразить на странице HTML таблицу, показывающую результаты выполнения методов toString и valueOf всех встроенных объектов JavaScript.

 

Упражнение 6.  
Разработать страницу HTML со встроенным сценарием, который получает введенный пользователем код JavaScript в текстовом поле страницы и выполняет его. Получить строку из текстового поля страницы HTML <input name=txt1 type=text size=40> можно, используя свойство value объекта с идентификатором, равным значению атрибута name текстового поля fromText = txt1.value Интерпретацию строки можно организовать, используя кнопку <input type=button value="Интерпретировать" xnclick="eval(txt1.value)">

 

Упражнение 7.  

Написать сценарий, который кодирует строку, содержащую все небуквенные символы клавиатуры тремя возможными способами и отобразить результаты в виде таблицы:

Символ escape encodeURI encodeURIComponent
  %20 %20 %20
` %60 %60 %60
~ %7E ~ ~
! %21 ! !
@ @ @ %40
# %23 # %23
...

 

 

Создание собственных объектов

Объектная модель JavaScript отличается от объектных моделей других объектно-ориентированных языков тем, что в ней объекты создаются на основе прототипов.

Для создания объектов в JavaScript можно использовать объектный литерал или специальным образом написанную функцию - конструктор объекта.

Объектный литерал представляет собой заданную в фигурных скобках последовательность свойств объекта и их значений. Свойства и значения задаются парами, разделенными символом :. Таким образом, объектный литерал имеет следующий синтаксис:

{prop1:value1, ..., propN:valueN}

Значением свойства может быть любой поддерживаемый JavaScript тип данных, включая объект:

var Basil = {name:"Basil",surname: "Ivanoff", university:{name:"PGU",faculty:"AM",cours:5}}

В качестве значения может снова выступать объектный литерал. В этом случае "точечная" нотация может быть продолжена для получения соответствующего свойства объекта, являющегося свойством созданного объекта.

alert(Basil.university.name)

Если в качестве значения свойства указывается ссылка на объект-функцию, то такое свойство на самом деле является методом создаваемого объекта:

var Cat = {name:"Mourik", color:"red", voice:mew}; function mew(){ alert("mew... mew...")}

Вызов метода осуществляется по всем правилам вызова функций JavaScript - указывается имя метода и при необходимости передаются ему фактические параметры:

Cat.voice();

Но реально будет вызвана и выполнена функция, реализующая указанный метод (в нашем примере mew()).

Второй способ позволяет быстро создавать экземпляры объекта определенного типа через специальную функцию-конструктор. Если с помощью объектного литерала мы непосредственно создаем экземпляр объекта и сохраняем в некоторой переменной ссылку на него, то здесь мы сначала "описываем" в конструкторе его свойства и методы, а потом операцией new создаем экземпляры этого типа объекта:

// Объявление конструктораfunction CatWithoutOwner(sName, sColor) { this.name = sName this.color = sColor}// Создание экземпляраmyCat = new CatWithoutOwner("Mourik", "red")

Ключевое слово this в конструкторе предназначено для ссылки на конкретный экземпляр объекта, создаваемый операцией new. (Если в функции используется ключевое слово this, то это обязательно конструктор объекта.)

Как и в случае с объектными литералами, свойства объекта, определяемые в его конструкторе, сами могут быть объектами:

// Конструктор объекта personfunction person(name, age) { this.name = name this.age = age}// создаем экземпляр объекта personalex = new person("Alex", 50) // Конструктор объекта CatWithOwnerfunction CatWithOwner(sName, sColor, sOwner) { this.name = sName this.color = sColor this.owner = sOwner}// Создает экземпляр объекта CatWithOwnercat = new CatWithOwner("Mourik", "red", alex) // Отображаем имя владельцаalert(cat.owner.name)

Отличительной особенностью объектной модели JavaScript является то, что после создания экземпляра объекта к нему можно добавлять новые свойства и методы, которые будут присущи только этому конкретному экземпляру. Для этого достаточно в точечной нотации указать имя нового свойства и присвоить ему значение:

cat.age = 6;cat.voice = mew

Теперь у объекта cat появилось свойство age и метод voice, но только у этого объекта. Создаваемые конструктором CatWithOwner() объекты не будут иметь указанных свойства и метода.

Но в JavaScript можно (после написания конструктора) в любой момент (чтобы не менять конструктор) добавить свойства и метолы непосредственно к объектному типу. Это приведет к тому, что создаваемые после этого экземпляры объектов с помощью того же конструктора будут обладать добавленными свойствами и методами. Для этих целей используется свойство prototype "объектного типа", совпадающего с именем конструктора:

CatWithOwner.prototype.age = nullCatWithOwner.prototype.voice = mew // теперь создаем экземплярvar cat1 = new CatWithOwner("Mourik", "red", alex) // у него есть свойство age (значение null)// и метод voice()alert(cat1.age);cat1.voice(); // можем изменить значение свойства agecat1.age = "red"

В конструкторе объекта вместо имен свойств (да и методов) можно использовать индексы:

function CatWithOwner(sName, sColor, sOwner) { this[1] = sName this[2] = sColor this.owner = sOwner} cat1 = new CatWithOwner("Mourik", "black", alex)

Теперь к свойствам, соответствующим имени и цвету, можно обращаться по индексу:

alert(cat1[1])

Индексацию можно использовать и при доступе к свойствам, определенным с помощью имени, но в этом случае в качестве индекса берется строка с именем свойства:

alert(cat1["owner"])

Для определения методов объекта в конструкторе следуем по схеме, аналогичной определению методов объекта в его конструкторе - определяем свойство, имеющее значением ссылку на функцию, реализующую создаваемый метод:

function who() { var result = "Кот " + this.name + ",\nвладелец которого" + this.owner.name return result} // Новый конструктор объекта CatWithOwnerfunction CatWithOwner(sName, sColor, sOwner) { this.name = sName this.color = sColor this.owner = sOwner this.whose = who} // Новый котvar cat2 = new CatWithOwner(); // Чей это котalert(cat2.who())

В JavaScript не предусмотрено операции удаления объектов из памяти - они все удаляются либо по завершению работы сценария (закрытие страницы HTML в браузере), либо по завершению работы функции, в которой были созданы локальные объекты.

Существует операция delete, позволяющая удалить свойство объекта или элемента массива. Удалять можно только свойства созданных пользователем собственных объектов или свойства встроенных объектов, которые пользователь к ним добавил:

myobj = new Number();myoj["prop"] = "*********"delete myobj.prop

В завершение рассказа о пользовательских объекта, в конструкторах которых применялось ключевое слово this для создания ссылки на текущий экземпляр объекта, напомним еще об одном случае использования этого ключевого слова. Его можно использовать в коде обработчика события элемента HTML для ссылки на объект, соответствующий этому элементу HTML:

<INPUT TYPE="text" NAME="age" SIZE=3 xnChange="validate(this)">

Здесь ключевое слово this ссылается на поле ввода и ссылка на него передается в функцию validate(), вызываемую при возникновении события изменения содержимого этого поля.

Упражнение 1.  
Создать массив на основе объекта Object. Посмотреть, если у него свойство length, присущее массивам, созданным с помощью объекта Array.

 

Упражнение 2.  
Распечатать свойство constructor для всех известных объектов JavaScript. С помощью свойства prototype объекта Object для всех создаваемых в сценарии объектов добавить метод propertiesList(), возвращающий массив, содержащий названия всех свойств объекта и их значения.

 

Упражнение 3.  
Разработать объект Collection, позволяющий хранить и выбирать любые объекты JavaScript с использованием строкового ключа. Реализовать методы этого объекта: add(ключ, объект) - добавление объекта в семейство Collection, remove(ключ) - удаление объекта, count() - возвращает количество объектов в семействе, item(ключ) - возвращает объект по значению его ключа.

 








Дата добавления: 2016-02-11; просмотров: 799;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.019 сек.