Строки, математические выражения и даты

До этого момента большинство из рассмотренных объектов имели непосредственное отношение к объектной модели документа. Однако, между объектной моделью документа и языком JavaScript существует четкое размежевание. В языке используются собственные объекты, которые полностью независимы от объектов модели документа. Эти объекты определяются таким образом, что если бы разработчик сценария захотел использовать JavaScript в качестве языка программирования для полноценного решения другой задачи, то в этом языке все же можно для управления текстом, проведения сложных математических вычислений (выходящих за пределы элементарных математических операций) и задания дать использовать основные из упомянутых выше программных средств. Формальное описание соответствующих объектов можно найти в инструкциях стандарта ЕСМА-262.

Объекты базового языка

Не только для новичков в программировании, но даже и для вполне опытных пользователей, которым не приходилось сталкиваться с объектно-ориентированным программированием, бывает крайне сложно привыкнуть к объектам, особенно если последние определяют что-то, имеющее физическую интерпретацию весьма сомнительного характера. Например, не представляет большого труда свыкнуться с мыслью, что кнопка на странице является объектом. У нее есть несколько свойств, которые поддаются логическому восприятию. А вот как быть со строкой или символом? В любой объектно-ориентированной среде, каковой выступает и JavaScript, все, что может изменяться, трактуется как объект, - каждый фрагмент данных, начиная с логических значений и заканчивая датами. Каждый такой объект, вероятнее всего, имеет одно или более свойств, которые призваны помочь в определении его содержимого. Каждый объект также имеет методы, определяющие, какие задачи объект может выполнять и что программист может делать с объектом.

Все объекты, которые не относятся к объектной модели документа, будем называть объектами базового языка. На этом уроке основное внимание уделено объектам типа String, Math и Date.

Строковые объекты

В предыдущих главах строковые объекты String уже неоднократно использовались. Строкой считается любой текст, заключенный в кавычки. Кавычки могут быть двойными или одинарными. Это позволяет вставлять одну строку в другую, что приходится часто выполнять при управлении обработчиками событий. В приведенном ниже примере методу alert() в качестве параметра нужно задать заключенную в кавычки строку. Но при этом сам вызов метода также осуществляется с использованием кавычек:

onClick="alert( 'Hello, all')"

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

Есть два способа присваивания значения строчной переменной. Наиболее просто эта задача решается с использованием оператора обычного присваивания:

var myString = "Howdy"    

Этот подход превосходно срабатывает во всех, за редким исключением, случаях. Начиная с Navigator 3 и Internet Explorer 4 строки можно создавать с использованием более формального синтаксиса на основе ключевого слова new и конструктора функции (конструктор создает новый объект):

var myString = new String("Howdy")

Какой бы способ из описанных выше ни использовался для инициализации строковой переменной, она становится доступной для всех методов объекта String.

Объединение строк

Соединение двух строк в одну называется объединением (или конкатенацией) строк. Этот термин уже встречался ранее. Для объединения строк нужно воспользоваться одним из двух предусмотренных для этого случаях применения JavaScript-операторов. Уже в первом сценарии урока №1 можно было увидеть, как оператор суммирования (+) использовался для объединения нескольких строк с целью создания на загружаемой Web-странице динамически отображаемого текстового сообщения:

document.write(" <B>" + navigator.appName + "</B>.")

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

var msg = "Four score" 
msg = msg + " and seven" 
msg = msg + " years ago"

Другой оператор, оператор дополнения, предлагает более компактную форму записи. Символ этого оператора - это знак плюс и знак равенства, не разделенные пробелом (+=). Использование этого оператора эквивалентно добавлению в конец переменной, стоящей слева от оператора, того выражения, что находится справа от оператора. Поэтому команды из вышеприведенного примера упростятся до следующего представления:

var msg = "Four score" 
msg += " and seven" 
msg += " years ago"

При необходимости можно поступить еще проще.

var msg = "Four score" 
msg += " and seven" + " years ago"

Оператор приращения удобно использовать, когда нужно собрать вместе фрагменты текста HTML для отображения его в текущем документе или другом окне.

Методы строковых объектов

Из всех основных объектов JavaScript, объект String имеет наиболее богатый набор методов. Многие из этих методов используются для извлечения фрагментов строк. Другая группа методов, которая используется значительно реже, задается с помощью стилевых дескрипторов (эквивалент дескрипторов, определяющих размер шрифта, стиль и др. параметры, в сценарии).

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

var result = string.methodName()

В следующем разделе описано несколько полезных методов строковых объектов, которые доступны в браузерах всех типов и версий.

Изменение регистра

Существует два метода, которые преобразуют всю строку в символы верхнего или нижнего регистра (т.е. все буквы становятся либо строчными, либо прописными соответственно):

var result = string.toUpperCase() 
var result = string.toLowerCase()

Названия этих методов говорят сами за себя (to upper case - в верхний регистр и to lower case - в нижний регистр). Указанные методы могут пригодиться в том случае, если нужно сравнить две строки без учета регистра символов (например, когда строка в таблице поиска сравнивается с введенной пользователем). Поскольку методы не изменяют содержимое исходных строк, используемых в выражениях, в данном случае можно просто сравнить результаты вызова соответствующих методов:

var foundMatch = false 
if (stringA.toUpperCase() == stringB.toUpperCase()) {
foundMatch = true 
}

Поиск строк

Для того чтобы определить, содержится ли одна строка внутри другой строки, используется метод string.indexOf(). Даже при работе с данными объектов JavaScript это весьма полезная и часто используемая информация. Например, одно из свойств объекта navigator (navigator.userAgent) позволяет узнать много интересного о браузере, с помощью которого выполняется загрузка страницы. Сценарий может проверить значение соответствующего свойства на наличие в нем, скажем, фрагмента Win. Полученные данные позволяют определить, какие операционные системы используются посетителем. Часто внутри очень длинной строки скрывается коротенький текстовый фрагмент особой важности, поэтому каждый сценарий должен уметь определять, содержится ли одна строка в другой - где бы она ни располагалась.

Метод string.indexOf() возвращает в качестве значения число, определяющее индекс (начальное значение нуль) того символа длинной строки, с которого начинается искомая вложенная строка. Если совпадение не обнаружено, то возвращается значение -1. Для выяснения, содержится ли данная строка в длинном текстовом фрагменте, достаточно просто убедиться, что возвращаемое методом значение отлично от -1.

В этом методе указываются две строки: короткая и длинная. Та строка, что длиннее, в ссылке задается слева от названия метода. Та строка, что покороче, указывается в качестве параметра метода indexOf(). Чтобы продемонстрировать, как этот метод применяется на практике, приведен следующий фрагмент кода. В нем выясняется, использует ли пользователь операционную систему Windows.

var isWindows = false 
if (navigator.userAgent.indexOf("Win") != -1) {
isWindows == true 
    }

В условии конструкции if использован оператор неравенства (!=). Он определяется, как "не равно".

Извлечение копий символов и подстрок

Для того чтобы извлечь в определенной позиции строки отдельный символ, используется метод chartAt(). Параметр этого метода- это индекс (начальное значение нуль) искомого символа. Когда выше было указано извлечь символ, то это не подразумевало удаление. Извлечение скорее напоминает "фотографирование" символа. Исходная строка не изменится при этом никоим образом.

Например, рассмотрим сценарий в основном окне, который проверяет переменную stringA другого окна, в котором отображаются планы различных зданий. Когда в окне представляется план здания Building С, значение переменной stringA равно "Building С". Символ, обозначающий здание, всегда представляется в десятой позиции (т.е. индексом номер 9, если начинать отсчет с нуля), так что сценарию достаточно проверить только один этот символ, чтобы идентифицировать карту, отображенную в текущий момент в окне:

var stringA = "Building С"
var bldLetter = stringA.charAt(9)
// Результат: bldLetter = "С"

Другой метод- string.substring()- позволяет извлекать последовательность символов по известному индексу начала и окончания подстроки, копию которой нужно получить. Здесь обязательно обратите внимание на тот факт, что последний символ такой подстроки (который соответствует конечному индексу) не извлекается. Все остальные символы, начиная с символа, соответствующего начальному индексу, и заканчивая символом, стоящим перед тем, что отвечает конечному индексу, будут извлечены в виде единой подстроки.

Строка, из которой извлекается фрагмент, в ссылке на метод располагается слева от названия метода. Два параметра, передаваемых методу, соответствуют начальному и конечному индексу (если начинать отсчет с нуля) извлекаемой подстроки:

var stringA = "banana daiquiri" 
var excerpt = stringA.substring(2,6) 
// Результат: excerpt = "nana"

Операции со строками в JavaScript, по сравнению с некоторыми другими языками, выглядят несколько громоздкими. Такие высокоуровневые понятия, как слова, предложения или абзацы здесь просто отсутствуют. Поэтому часто для управления методами строчных объектов затрачиваются незначительные усилия, от чего может сложиться впечатление, что это достаточно просто. Чтобы охладить пыл энтузиастов, я бы посоветовал им применить полученные знания в области вычисления выражений для того чтобы проверить, что же будет, если использовать нетривиального характера структуры, вложенные одна в другую. Например, в следующем фрагменте нужно создать новую строку, идентичную более длинной строке, за исключением первого слова, которое в новой строке должно отсутствовать. Примите во внимание, что первое слово, в принципе, может быть любой длины. Поэтому во втором операторе, чтобы найти первый пробел, используется метод string.indexOf(). К индексу первого пробела в строке прибавляется единица, определяя тем самым начальный индекс для метода string.substring(). Для определения второго параметра этого метода используется свойство length строки (оно на единицу больше того числа, которое передается в качестве параметра).

var stringA = "The United States of America"
var excerpt = stringA.substring(stringA.indexOf(" ") + 1, stringA.length)
// Результат: excerpt = "United States of America"

Создание подобного рода кода является далеко не самым веселым занятием, особенно если эту задачу приходится решать довольно часто. Поэтому не лишено смысла создание собственной библиотеки функций, управляющих строками, которые потом можно использовать каждый раз при написании сценариев, в которых используются строковые данные. Более мощные средства обработки строк, реализуемые в виде обычных выражений, поддерживаются в NN4+ и IE4+ , но это выходит за рамки данного учебного курса…

Объект Math

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

Все эти возможности предоставляются объектом Math. Этот объект выгодно отличается от всех остальных объектов JavaScript в том смысле, что для работы с ним не нужно создавать его копии. Вместо этого просто вызываются методы и свойства единственного объекта Math. Объект Math является производным от окна или фрейма, однако на ход выполнения сценария это совершенно не влияет. Программисты называют такого рода фиксированные объекты статичными. Объект Math (пишется с большой буквы М) обязательно должен указываться в ссылке на свойство или метод. Свойства объекта Math - это постоянные значения (константы), вроде числа "Пи" или корня квадратного из двух:

var piValue = Math.PI 
var rootOfTwo = Math.SQRT2

Методы объекта Math покрывают широкий диапазон, вплоть до тригонометрических и других математических функций, управляющих числовыми значениями, которые предопределены в сценарии. Например, следующим образом в сценарии определяется, какое из двух чисел больше:

var larger = Math.max(value1, value2) 

А вот как число возводится в десятую степень:

var result = Math.pow(value1, 10)

Более полезный, пожалуй, метод, с помощью которого можно округлить значение до ближайшего целого числа:

var result = Math.round(value1)

Еще один часто используемый метод - это генерирование случайного числа с помощью объекта Math. Метод Math.random() возвращает в качестве значения число с плавающей точкой в диапазоне от 0 до 1. Если вами создается сценарий карточной игры, то в нем обязательно понадобится генерировать случайные числа от 1 до 52. При бросании кубика задаются случайные числа в диапазоне от 1 до 6. Для того чтобы сгенерировать целое число в диапазоне от нуля до любого другого числа, можно воспользоваться следующей формулой:

Math.floor(Math.random() * (n+1)) ,
                  где n - верхний предел диапазона. 
				  

Метод Math.floor() возвращает целую часть любого числа с плавающей точкой. Для генерирования случайных чисел в диапазоне между единицей и большим единицы числом используется формула:

Math.floor(Math.random() * n) +1,
где n - опять таки является верхним пределом диапазона. 

Для игры с подбрасыванием кубика случайное число в диапазоне 1-6 задается следующим образом:

newDieValue = Math.floor(Math.random()*6) +1

Единственное, в чем JavaScript не очень силен, за исключением версий IE5.5 и NN6, - это в форматировании чисел. В числах с плавающей точкой после десятичной точки может отображаться не больше десятка цифр. Добавьте также всевозможные погрешности в операциях с числами с плавающей точкой, которые зависят от используемой операционной системы, особенно для ранних версий браузеров. Для браузеров, созданных ранее IE5.5 и NN6, форматирование любого типа данных приходится выполнять самостоятельно - для долларов и центов, например, с помощью отдельных сценариев. Но я не думаю, что кому-то из вас понадобится точность до десяти знаков после запятой.

Объект Date

Работа с датами в JavaScript, выходящая за рамки простых задач, может быть весьма непростым делом. Большинство проблем возникает оттого, что дата и время рассчитываются непосредственно по Гринвичскому времени (Greenwich Mean Time - GMT). При этом подразумевается, что время на часах компьютера пользователя выставлено правильно. Такие особенности лучше оставить для более глубокого изучения. Здесь же будут рассмотрены только основные способы управления объектом Date в JavaScript.

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

var today = new Date()

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

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

С помощью объекта Date можно определить дату и момент времени как в прошлом, так и будущем, для чего полученная информация задается в качестве параметров функции конструктора объекта Date.

var someDate = new Date ("Month dd, yyyy hh:mni:ss")
var someDate = new Date("Month dd, yyyy")
var someDate = new Date(yy,mm,dd,hh,mm,ss)
var someDate = new Date(yy,mm,dd)
var someDate = new Date(GMT milliseconds from 1/1/1970)

Если теперь попробовать просмотреть ряд объектов date, JavaScript преобразует соответствующие значения в строку, содержащую время текущего часового пояса, заданную согласно настройкам папки Панель управления компьютера пользователя.

Часы персонального компьютера представляют текущие дату и время в таком виде, как они задаются на экране обычных часов (даже несмотря на то, что JavaScript управляет временем в миллисекундах соответственно времени Гринвичского меридиана). Тем не менее, в результате применения некоторых методов к экземпляру объекта даты, из него можно извлечь отдельные компоненты даты. В таблице 1 приведен краткий список соответствующих свойств и их описания.

Таблица 1. Некоторые методы объекта Date

МетодДиапазон значений Описание
dateObj.getTime() 0-. . . Количество миллисекунд начиная с 1 января 1970 года 00:00:00 по Гринвичскому времени
dateObj.getYearO 70-… Заданный год минус 1900. Четырехзначное число для года, начиная с 2000 и позже
dateObj.getFullYear() 1970-.. Четырехзначное число, определяющее год. Поддерживается броузерами начиная с четвертой версии
dateObj.getMonth() 0-11 Месяц года (Январь=0)
dateObj.getDate()1- 31 Число месяца
dateObj.getDay()0-6День недели (Воскресенье=0 )
dateObj.getHours()0-23Время суток в часах
dateObj.getMinutes()0-59Минуты
dateObj.getSeconds()0-59Секунды
dateObj.setTime(val)0-.. .Задает количество миллисекунд начиная с 1 января 1970 года 00:00:00 по Гринвичскому времени
dateObj.setYear(val)70-...Задает год минус 1900. Четырехзначное число для года, начиная с 2000 и позже
dateObj.setMonth(val)0-11Задает месяц года (Январь=0)
dateObj.setDate(val)1-31Задает число месяца
dateObj.setDay(val)0-6Задает день недели (Воскресенье=0 )
dateObj.setHours(val)0-23Задает время суток в часах
dateObj.setMinutes(val)0-59Задает минуты
dateObj.setSeconds(val)0-59Задает секунды

Будьте очень внимательным при работе со значениями, диапазон возможных изменений которых начинается с нуля. Особенно это касается месяцев. Методы getMonth() и setMonth() могут возвращать в качестве значения нуль. Так что соответствующее число на единицу меньше, чем номер месяца (например, январю соответствует 0, декабрю -11).

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

Определение даты

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

Листинг 1. Вычисление даты и времени
<HTML>
<HEAD>
<TITLE>Date Calculation</TITLE>
<SCRIPT LANGUAGE ="JavaScript">
function nextWeek() {
  var todayInMS = today.getTime()
  var nextWeekInMS = todayInMS + (60 * 60 * 24 * 7 * 1000)
  var next= new Date(nextWeekInMS)
 return next
}
</SCRIPT>
</HEAD>
<BODY> Today is:
<SCRIP-T LANGUAGE="JavaScript">
var today = new Date()
document.write(today)
</SCRIPT>
<BR>
Next week will be:
<SCRIPT LANGUAGE="JavaScript">
document.write(nextWeek())
</SCRIPT>
</BODY>
</HTML>

В теле документа первый сценарий запускается при загрузке страницы, определяя глобальную переменную (today), значение которой равно текущей дате и времени. Строковый ее эквивалент отображается на странице. Во втором сценарии упомянутого раздела метод document.write() вызывает функцию nextWeek(), определяющую значение, которое впоследствии будет отображено на странице. Эта функция использует глобальную переменную today и копирует ее значение в миллисекундах в новую переменную todayInMS. Для вычисления даты через семь дней после текущей в следующем операторе к текущей дате (в миллисекундах) добавляется число миллисекунд в семи днях (60 секунд умножить на 60 минут, умножить на 24 часа, умножить на 7 дней и умножить на 1000 миллисекунд). Далее в сценарии задается новый экземпляр объекта с рассчитанным суммарным числом миллисекунд. С этой целью вызывается конструктор объекта Date с данным числом миллисекунд в качестве параметра. Возвращаемым значением является объект даты, который автоматически преобразуется к строковому типу для отображения на странице. Создание с помощью JavaScript нового объекта даты с подсчитанным числом миллисекунд - более надежный вариант, чем простое числовое добавление 7 дней к значению, возвращаемому методом getDate() объекта даты. JavaScript автоматически определяет количество дней в данном месяце и другие подобные параметры.

Тех, кто будет и дальше использовать в своих сценариях даты, ждет много откровенных неожиданностей в поведении дат и непредвиденных сложностей. Однако, конечный результат стоит затраченных усилий.




Упражнения к уроку.


Hosted by uCoz