JavaScript (основы). Глава 7. Работа с объектами
Оглавление | Назад | Вперёд | ИндексГлава 7. Работа с объектами
JavaScript разработан на основе простой объектной парадигмы. Объект это конструкция со свойствами, которые являются переменными JavaScript или другими объектами. Объект также может иметь ассоциированные с ним функции, которые известны как methods\методы объекта. Помимо предопределённых серверных и клиентских объектов Navigator'а, можно создавать пользовательские объекты.
В главе рассматривается, как использовать объекты, свойства, функции и методы и как создавать Ваши собственные объекты.
В главе имеются следующие разделы:
Объекты и свойства
Объект в JavaScript имеет ассоциированные с ним свойства. Вы получаете доступ к этим свойствам объектов с помощью простой нотации:
И имя объекта, и имя свойства чувствительны к регистру символов. Вы определяете свойство, присваивая ему значение. Например, имеется объект myCar (для упрощения будем всё время предполагать, что объект уже существует). Вы можете создать его свойства make, model и year:
myCar.model="Mustang"
myCar.year=1969;
Массив это упорядоченный набор значений, ассоциированных с одним именем переменной. Свойства и массивы в JavaScript тесно связаны; фактически это два разных интерфейса для одной структуры данных. Так, например, Вы можете получить доступ к свойствам объекта myCar так:
myCar["model"]="Mustang"
myCar["year"]=1967
Массив этого типа известен как ассоциативный массив, поскольку индекс каждого элемента также ассоциирован со строковым значением. В качестве иллюстрации: следующая функция отображает свойства объекта, когда Вы передаёте объект и имя объекта в качестве аргументов этой функции:
function show_props(obj, obj_name){
var result=""
for (var i in obj)
result += obj_name + "." + i + "=" + obj[i] + "\n"
return result
}
Так, вызов функции show_props(myCar, "myCar") возвратит:
myCar.model=Mustang
myCar.year=1967
Создание новых объектов
В JavaScript имеются предопределённые объекты. Кроме того, Вы можете создавать Ваши собственные объекты. В JavaScript 1.2 Вы можете создавать объект с использованием инициализатора объекта. Альтернативно, Вы можете сначала создать функцию-конструктор, а затем инстанциировать объект с использованием этой функции и операции new.
Использование инициализаторов объектов
Помимо создания объектов с использованием функции-конструктора, Вы можете создавать объекты с использованием инициализатора объекта. Использование инициализаторов объектов иногда называют созданием объектов с помощью литеральной нотации. "Инициализатор объекта" составлен в терминологии C++.
Синтаксис объекта, использующего инициализатор объекта, таков:
objectName={property1:value1, property2:value2,…, property N:value N }
где objectName это имя нового объекта, каждое property I это идентификатор (имя, число или строковой литерал), а каждое value I это выражение, значение которого присваивается свойству property I.
objectName и присвоение не обязательны. Если Вам не нужно ссылаться на данный объект, Вы можете не присваивать его переменной.
Если объект создаётся инициализатором в скрипте верхнего уровня, JavaScript интерпретирует этот объект всякий раз при вычислении выражения, содержащего литерал объекта. К тому же инициализатор, используемый в функции, создаётся при каждом вызове функции.
Этот оператор создаёт объект и присваивает его переменной x, если, и только если, выражение cond - true.
Следующий пример создаёт myHonda с тремя свойствами. Заметьте, что свойство engine является также объектом со своими собственными свойствами.
myHonda={color:"red",wheels:4,engine:{cylinders:4,size:2.2}}
Вы можете также использовать инициализаторы объектов для создания массивов. См. "Литералы Массива".
JavaScript 1.1 и предыдущие версии.
Вы не можете использовать инициализаторы объектов. Вы можете создавать объекты только путём использования функций-конструкторов или функцией, предоставляемой другим объектом для этой цели. См. "Использование Функции-Конструктора".
Использование функции-конструктора
Альтернативно можно создавать объект в 2 этапа:
- Определить тип объекта, написав функцию-конструктор.
- Создать экземпляр объекта с помощью операции new.
Для того чтобы определить тип объекта, создайте функцию для типа объекта, которая специфицирует имя, свойства и методы. Например, Вы хотите создать тип объекта для автомобилей/cars. Вы называете тип объекта car и хотите, чтобы у него были свойства make, model, year и color. Для реализации этого Вы должны написать следующую функцию:
function car(make, model, year){
this.make=make
this.model=model
this.year=year
}
Обратите внимание на использование this для присвоения значений свойствам объекта на основе значений, передаваемых в функцию.
Теперь Вы можете создать объект mycar:
mycar=new car("Eagle", "Talon TSi", 1993)
Этот оператор создаёт объект mycar и присваивает специфицированные значения его свойствам. Тогда значением mycar.make будет строка "Eagle", mycar.year это целое число 1993 и так далее.
Вы можете создать любое количество объектов car через вызов new. Например,
kenscar=new car("Nissan", "300ZX", 1992)
vpgscar=new car("Mazda", "Miata", 1990)
Объект может иметь свойство, которое само является объектом. Например, Вы определяете объект person:
function person(name, age, sex){
this.name=name
this.age=age
this.sex=sex
}
и инстанциируете 2 новых person -объекта:
rand=new person("Rand McKinnon", 33, "M")
ken=new person("Ken Jones", 39, "M")
Затем Вы можете переписать определение car и включить в него свойство owner, которое принимает person -объект:
function car(make, model, year, owner){
this.make=make
this.model=model
this.year=year
this.owner=owner
}
Теперь можно инстанциировать новые объекты:
car1=new car("Eagle", "Talon TSi", 1993, rand)
car2=new car("Nissan", "300ZX", 1992, ken)
Обратите внимание, что вместо передачи литеральной строки или целочисленного значения при создании новых объектов, эти операторы передают объекты rand и ken как аргументы для owner. Затем, если Вы хотите вычислить имя владельца автомобиля car2, Вы можете получить доступ к следующему свойству:
Заметьте, что Вы всегда можете добавить свойство к ранее определённому объекту. Например, оператор
добавляет свойство color объекту car1 и присваивает ему значение "black." Однако это не влияет на все другие объекты. Для добавления свойства всем объектам данного типа Вы должны добавить свойство в определение типа объекта car.
Индексирование свойств объекта
В JavaScript 1.0 Вы можете обратиться к свойствам объекта по имени или по индексу. В JavaScript 1.1 или позднее, однако, если Вы первоначально определили свойство по имени, Вы обязаны всегда обращаться к нему по имени и, если Вы первоначально определили свойство по индексу, Вы обязаны всегда обращаться к нему по индексу.
Это применяется при создании объекта и его свойств функцией-конструктором, как в предыдущем примере с типом объектов сar, и при определении индивидуальных свойств явным образом (например, myCar.color="red"). Так, если Вы определяет первоначально свойства объекта индексированием, как myCar[5]="25 mpg", Вы в дальнейшем обращаетесь к свойству myCar[5].
Исключением из этого правила является объект, отражённый из HTML, такой как массив forms. Вы можете всегда обратиться к объектам в этих массивах по порядковому номеру (в зависимости от места в документе) или по именам (если определены). Например, если второй тэг <FORM> в документе имеет в атрибуте NAME значение "myForm", Вы можете обратиться к форме document.forms[1] or document.forms["myForm"] или document.myForm.
Определение свойств для типа объектов
Вы можете добавить свойство к ранее определённому типу объектов, используя свойство prototype. Оно определяет свойство, которое используется всеми объектами специфицированного типа, а не только одним экземпляром объекта. Следующий код добавляет свойство color всем объектам типа car и присваивает значение свойства color объекту car1.
car1.color="black"
См. свойство prototype объекта Function в книге Клиентский JavaScript. Справочник.
Метод это функция, ассоциированная с объектом. Вы определяете метод так же, как и стандартную функцию. Затем Вы используете для ассоциирования функции с существующим объектом следующий синтаксис:
object.methodname=function_name
где object это существующий объект, methodname это имя, присвоенное Вами методу, а function_name это имя функции.
Вы можете затем вызвать метод в контексте объекта:
Вы можете определить методы для типа объектов, включив определение метода в функцию-конструктор. Например, Вы могли бы определить функцию форматирования и отображения свойств ранее определённых объектов car; например,
var result="A Beautiful " + this.year + " " + this.make
+ " " + this.model
pretty_print(result)
}
где pretty_print это функция для отображения горизонтальной линии и строки. Обратите внимание на использование this для обращения к объекту, которому принадлежит данный метод.
Вы можете сделать эту функцию методом объектов типа car, добавив оператор
к определению типа объектов. Так, полное определение car теперь будет выглядеть:
function car(make, model, year, owner){
this.make=make
this.model=model
this.year=year
this.owner=owner
this.displayCar=displayCar
}
Затем можно вызвать метод displayCar для каждого объекта:
car2.displayCar()
Это даст вывод показанный на рисунке.
Рисунок 7.1 Вывод метода
Использование this для ссылок на объект
В JavaScript имеется специальное слово this, которое можно использовать в методе для обращения к текущему объекту. Например, у Вас имеются: функция validate для проверки свойства value объекта, объект и значения high и low:
function validate(obj, lowval, hival){
if((obj.value < lowval) || (obj.value > hival))
alert("Invalid Value!")
}
Затем Вы можете вызывать validate в обработчике события onChange каждого элемента формы, используя this для передачи ему элемента формы, как в следующем примере:
<INPUT TYPE=text NAME="age" SIZE=3
onChange="validate(this, 18, 99)">
В общем случае, this ссылается в методе на вызывающий объект.
При сочетании со свойством form, this может ссылаться на родительскую форму текущего объекта. В следующем примере, форма myForm содержит Text -объект и кнопку. Когда пользователь нажимает кнопку, в значение Text -объекта устанавливается имя формы. Обработчик onClick кнопки использует this.form для обращения к родительской форме, myForm.
Form name:<INPUT TYPE=text NAME="text1" VALUE="Beluga">
<P>
<INPUT NAME="button1" type=button VALUE="Show Form Name"
onClick="this.form.text1.value=this.form.name">
</FORM>
Удаление объектов
Вы можете удалить объект оператором delete. Следующий код показывает, как удалить объект.
delete myobj // удаляет объект и возвращает true
См. также "delete".
Вы можете удалить объект, установив ссылку на объекта в null (если это последняя ссылка на объект). JavaScript "финализирует" объект немедленно, как часть операции присвоения.
Вы не можете удалять объекты - они существуют, пока Вы не выйдете со страницы.
Предопределённые объекты ядра
В этом разделе рассматриваются предопределённые объекты ядра JavaScript: Array, Boolean, Date, Function, Math, Number, RegExp и String. Предопределённые клиентские объекты рассматриваются в Главе 11, "Использование Объектов Navigator-а".
Объект Array
В JavaScript нет типа данных array (массив). Однако Вы может использовать предопределённый объект Array и его методы для работы с массивами в Ваших приложениях. Объект Array имеет методы для работы с массивами: объединения, разворачивания и сортировки. Он имеет свойство для определения размера массива и другие свойства для использования с регулярными выражениями.
Массив это упорядоченный набор значений, к которым Вы обращаетесь по индексу или по имени. Например, у Вас имеется массив emp, в котором содержатся имена служащих, индексированные числом. Так, emp[1] это служащий номер 1, emp[2] - служащий номер 2 и так далее.
1. arrayObjectName=new Array(element0, element1,…, element N)
2. arrayObjectName=new Array(arrayLength)
arrayObjectName это либо имя нового объекта, либо свойство существующего объекта. При использовании свойств и методов объекта Array, arrayObjectName это либо имя существующего Array -объекта, либо свойство существующего объекта.
element0, element1,…, element N это список значений для элементов массива. Если специфицирована эта форма, массив инициализируется специфицированными значениями в качестве его элементов, а в свойство length массива устанавливается количество аргументов.
arrayLength это начальный размер массива. Следующий код создаёт массив из 5 элементов:
Литералы массива также являются Array -объектами; например, следующий литерал является Array -объектом.
coffees=["French Roast", "Columbian", "Kona"]
См. также "Литералы Массива".
Вы можете наполнить массив, присвоив значения его элементам. Например,
emp[2]="Phil Lesh"
emp[3]="August West"
Вы может наполнить массив также при его создании:
myArray=new Array("Hello", myVar, 3.14159)
Вы обращаетесь к элементам массива по порядковому номеру элемента. Например, Вы определили следующий массив:
myArray=new Array("Wind","Rain","Fire")
Затем Вы обращаетесь к первому элементу массива myArray[0], а ко второму элементу - myArray[1].
Индексы массива начинаются от 0, но размер массива (например, myArray.length) отражает реальное количество элементов массива.
Например, Вы определили массив:
myArray=new Array("Wind","Rain","Fire")
myArray.join() возвращает "Wind,Rain,Fire";
myArray.reverse разворачивает массив; myArray[0] становится "Fire", myArray[1] - "Rain", а myArray[2] - "Wind".
myArray.sort сортирует массив; myArray[0] становится "Fire", myArray[1] - "Rain", а myArray[2] - "Wind".
Следующий код создаёт двухмерный массив:
for (i=0; i < 4; i++){
a[i]=new Array(4)
for (j=0; j < 4; j++){
a[i][j]="["+i+","+j+"]"
}}
str="Row "+i+":"
for (j=0; j < 4; j++){
str += a[i][j]
}
document.write(str,"<p>")
}
Row 1:[1,0][1,1][1,2][1,3]
Row 2:[2,0][2,1][2,2][2,3]
Row 3:[3,0][3,1][3,2][3,3]
Массивы и регулярные выражения
Если массив является результатом совпадения регулярного выражения и строки, этот массив возвращает свойства и элементы, которые предоставляют информацию о совпадении. Массив является тогда return-значением regexp.exec, string.match и string.replace. Об использовании массивов с регулярными выражениями см. Главу 4 "Регулярные Выражения".
Объект Boolean
Объект Boolean является оболочкой вокруг примитивного типа данных Boolean. Используйте следующий синтаксис для создания Boolean -объекта:
booleanObjectName=new Boolean(value)
Не путайте примитивные Boolean-значения true и false со значениями true и false объекта Boolean. Любой объект, значение которого не undefined или null, и не объект Boolean со значением false, вычисляется в true, когда передаётся в условный оператор. См. "Оператор if…else".
Объект Date
В JavaScript нет типа данных data. Однако можно использовать объект Date и его методы для работы с датами и временем. Объект Date имеет большое количество методов для установки, получения и обслуживания дат.
Он не имеет свойств.
JavaScript обрабатывает даты аналогично Java. Эти 2 языка имеют много одинаковых методов для дат и хранят даты как количество миллисекунд относительно 1 января 1970 года, 00:00:00.
Диапазон объекта Date от -100,000,000 до 100,000,000 дней относительно 01 January, 1970 UTC.
dateObjectName=new Date([parameters])
где dateObjectName это имя создаваемого Date -объект; это может быть новый объект или свойство существующего объекта.
Например, Xmas95=new Date("December 25, 1995 13:30:00").
Если Вы опустите hours, minutes или seconds, значение будет установлено в 0.
Набором целочисленных значений для year, month, day, hour, minute и seconds. Например, Xmas95=new Date(1995,11,25,9,30,0).
Методы объекта Date для работы с датами и временем распадаются на следующие обширные категории:
Методами "get" и "set" Вы можете получать и устанавливать значения для секунд, минут, часа, дня недели, числа месяца, месяца и года. Имеется метод getDay, который возвращает день недели, но нет па́рного метода setDay, поскольку день недели устанавливается автоматически. Эти методы используют целые числа для представления этих значений:
Xmas95=new Date("December 25, 1995")
Тогда Xmas95.getMonth() возвращает 11, а Xmas95.getFullYear() возвращает 95.
Методы getTime и setTime используются для сравнения дат. Метод getTime возвращает количество миллисекунд, прошедших после January 1, 1970, 00:00:00 для Date -объекта.
Например, следующий код выводит количество дней оставшихся в текущем году:
endYear=new Date(1995,11,31,23,59,59,999) // устанавливает день и месяц
endYear.setFullYear(today.getFullYear()) // устанавливает в year текущий год
msPerDay=24 * 60 * 60 * 1000 // количество миллисекунд в сутках
daysLeft=(endYear.getTime() - today.getTime()) / msPerDay
daysLeft=Math.round(daysLeft) //возвращает количество оставшихся в году дней
Этот пример создаёт Date -объект today, который содержит текущую дату. Затем создаётся Date -объект endYear в него устанавливается значение текущего года. Далее, с использованием количества миллисекунд в сутки, вычисляется количество дней между текущей датой и endYear, с использованием getTime, которое затем округляется до целого количества суток.
Метод parse используется для присвоения значений из строк с датой существующим Date -объектам. Например, следующий код использует parse и setTime для присвоения значения даты объекту IPOdate:
IPOdate.setTime(Date.parse("Aug 9, 1995"))
Использование объекта Date: пример
В следующем примере функция JSClock() возвращает время в формате цифровых часов.
var time=new Date()
var hour=time.getHours()
var minute=time.getMinutes()
var second=time.getSeconds()
var temp="" + ((hour > 12) ? hour - 12: hour)
temp += ((minute < 10) ? ":0": ":") + minute
temp += ((second < 10) ? ":0": ":") + second
temp += (hour >= 12) ? " P.M.": " A.M."
return temp
}
Функция JSClock сначала создаёт новый Date -объект time; поскольку аргументы не заданы, объект создаётся с текущей датой и временем. Затем методы getHours, getMinutes и getSeconds присваивают значения текущих часа, минут и секунд переменным hour, minute и second.
Следующие четыре оператора строят строковое значение на основе этого времени.
Первый оператор создаёт переменную temp, присваивая ей значение условного выражения; если hour больше 12, ( hour - 13), иначе просто hour.
Следующий оператор присоединяет значение minute к temp. Если значение minute меньше 10, условное выражение прибавляет строку с предшествующим 0; иначе добавляет строку с разделяющим двоеточием. Затем оператор присоединяет значение секунд к temp тем же способом.
Наконец, условное выражение присоединяет "PM" к temp, если hour равно или больше 12; иначе присоединяет "AM" к temp.
Объект Function
Предопределённый объект Function специфицирует строку кода JavaScript, компилируемую как функция.
Для создания Function -объекта:
functionObjectName=new Function ([arg1, arg2,… argn], functionBody)
functionObjectName это имя переменной или свойства существующего объекта. Это может быть также объект с последующим именем обработчика события в нижнем регистре, например, window.onerror.
arg1, arg2,… argn это аргументы, используемые функцией как имена формальных аргументов. Каждое обязано быть строкой, соответствующей верному идентификатору JavaScript; например "x" или "theForm".
functionBody это строка, специфицирующая код JavaScript, компилируемый как тело функции.
Function -объекты вычисляются при каждом использовании. Это менее эффективно, чем объявление функции и вызов её в коде, поскольку объявленная функция компилируется.
Помимо рассмотренного здесь объявления, Вы можете также использовать оператор function. См. книгу Клиентский JavaScript. Справочник.
Следующий код присваивает функцию переменной setBGColor. Эта функция устанавливает цвет фона текущего документа.
var setBGColor=new Function("document.bgColor='antiquewhite'")
Для вызова Function -объекта Вы можете специфицировать имя переменной, как если бы это была функция. Следующий код выполняет функцию, специфицированную переменной setBGColor:
var colorChoice="antiquewhite"
if(colorChoice=="antiquewhite"){setBGColor()}
Вы можете присвоить функцию обработчику события одним из следующих способов:
1. document.form1.colorButton.onclick=setBGColor
2. <INPUT NAME="colorButton" type=button
VALUE="Change background color"
onClick="setBGColor()">
Создание переменной setBGColor, показанное выше, похоже на объявление следующей функции:
document.bgColor='antiquewhite'
}
Вы можете вкладывать функцию в функцию. Вложенная (внутренняя) функция является private для её содержащей (внешней) функции:
Объект Math
Предопределённый объект Math имеет свойства и методы для математических констант и функций. Например, свойство PI имеет значение pi (3.141…), которое Вы можете использовать в приложениях так:
Также и стандартные математические функции являются методами объекта Math. Сюда входят тригонометрические, логарифмические, экспоненциальные и др. функции. Например, если Вы хотите использовать тригонометрическую функцию sine/синус, Вы может записать:
Учтите, что все тригонометрические методы объекта Math принимают объекты в радианах.
В таблице дано резюме по методам объекта Math.
Таблица 7.1 Методы объекта Math
В отличие от многих других объектов, Вы никогда не создаёте собственные объекты Math. Вы всегда используете предопределённый объект Math.
Часто бывает удобнее использовать этот объект с оператором with, когда большой участок кода использует математические константы и методы, чтобы не нужно было постоянно печатать "Math". Например,
a=PI * r*r
y=r*sin(theta)
x=r*cos(theta)
}
Объект Number
Объект Number имеет свойства для числовых констант, таких как максимальное значение, не-число и бесконечность. Вы не можете изменять эти значения и используете их так:
smallestNum=Number.MIN_VALUE
infiniteNum=Number.POSITIVE_INFINITY
negInfiniteNum=Number.NEGATIVE_INFINITY
notANum=Number.NaN
Вы всегда обращаетесь к свойствам предопределённого объекта Number так, как показано выше, а не как к свойствам Number-объекта, созданного Вами.
В таблице дано резюме по свойствам объекта Number.
Таблица 7.2 Свойства объекта Number
Объект RegExp
Объект RegExp даёт возможность работать с регулярными выражениями. Он рассмотрен в Главе 4 "Регулярные Выражения".
Объект String
Объект String является оболочкой для примитивного типа данных string. Не путайте строковой литерал с объектом String. Например, следующий код создаёт строковой литерал s1 и String -объект s2:
s1="foo" //создаёт строковое литеральное значение
s2=new String("foo") //создаёт String-объект
Вы можете вызывать любой из методов объекта String в строковом литеральном значении - JavaScript автоматически конвертирует строковой литерал во временный String -объект, вызывает метод, затем уничтожает временный String -объект. Вы можете также использовать свойство String.length со строковым литералом.
Вы должны использовать строковые литералы, если только Вам не нужно обязательно использовать объект String, поскольку String -объекты могут иметь непредсказуемое поведение. Например:
s1="2 + 2" //создаёт строковое литеральное значение
s2=new String("2 + 2")//создаёт String-объект
eval(s1) //возвращает число 4
eval(s2) //возвращает строку "2 + 2"
Объект String имеет одно свойство, length, которое обозначает количество символов в строке. Например, следующий код присваивает переменной x значение 13, поскольку "Hello, World!" состоит из 13 символов:
x=mystring.length
Объект String имеет методы двух типов: возвращающие вариации самой строки, такие как substring и toUpperCase, и возвращающие HTML-форматированную версию строки, такие как bold и link.
Например, используя предыдущий пример, и mystring.toUpperCase() и "hello, world!".toUpperCase() возвратят строку "HELLO, WORLD!".
Метод substring принимает 2 аргумента и возвращает подстроку между двумя аргументами. Используя предыдущий пример, mystring.substring(4, 9) возвращает строку "o, Wo." См. метод substring объекта String в книге Клиентский JavaScript. Справочник.
Объект String также имеет несколько методов для автоматического HTML-форматирования, такие как bold для создания жирного начертания текста и link для создания гиперссылки. Например, Вы можете создать гиперссылку на воображаемый URL методом link:
mystring.link("//www.helloworld.com")
В таблице дано резюме по методам объекта String.
Таблица 7.3 Методы объекта String
Оглавление | Назад | Вперёд | Индекс