В этом небольшом фрагменте кода происходит очень многое. Вначале просто определяют две функции: multiply и add. Функция multiply просто перемножает все переданные ей числа. Аналогично, функция add складывает все переданные ей числа. Тонкости начинаются при использовании действий onclick двух созданных кнопок. Можно видеть, что при щелчке на любой из двух кнопок в функцию doAction передается объект. Ранее мы всегда передавали переменные или объекты HTML (такие, как поля ввода в предыдущем примере). В этом примере передаются функции. Функции можно передавать таким же способом, как и любой другой объект, и когда они передаются, их можно вызывать таким же способом, как и любую другую функцию. Изменяется только ее имя.
Таким образом функция doAction получает другую функцию в качестве аргумента! Если передается функция multiply, то функция doAction передает ей значения от 1 до 5, и мы получаем в результате 120. Если в doAction передается функция add, то ей также передаются значения от 1 до 5, и в результате мы получаем значение 15.
Это в действительности одно из наиболее мощных свойств JavaScript, и оно будет более подробно рассмотрено в следующих лекциях. Пока достаточно понять общий принцип.
Другим важным свойством функций является возможность вложения их друг в друга. JavaScript не поддерживает истинный объектно-ориентированный подход к проектированию, но это свойство обеспечивает очень похожие возможности.
Кроме вложения функций, важно отметить, что имеется несколько различных способов объявления функций:
function myFunction(){ function nestedFunction1(arg1, arg2, arg3){ alert(arg1+arg2+arg3); } var nestedFunction2 = function(arg1, arg2, arg3){ alert(arg1+arg2+arg3); } var nestedFunction3 = new Function('arg1, arg2, arg3', 'alert(arg1+arg2+arg3);'); }
В этом примере функции nestedFunction1, nestedFunction2 и nestedFunction3 являются одинаковыми по своим возможностям. Единственное различие состоит в том, как они определяются. nestedFunction1 объявлена, как это делалось раньше. Синтаксис для nestedFunction2 немного отличается. Мы задаем для функции переменную this.nestedFunction2. Синтаксис этого объявления будет следующий имяПеременной= function(аргументы){. Аналогично для функции nestedFunction3 задается переменная для новой функции. Однако это объявление существенно отличается, так как мы определяем функцию с помощью строк. Третий вариант используется редко, но является очень полезным, когда используется. Он позволяет создать строку, содержащую код выполняемой функции, а затем определить функцию с помощью этой строки.
В следующей лекции будут рассмотрены массивы.
Лекция 5. Строки, числа и массивы
Внутренняя работа присущих JavaScript объектов: строк, чисел и массивов.
До сих пор мы рассматривали языковые конструкции JavaScript: операторы if, циклы, функции и т.д. В этой лекции будет рассмотрена внутренняя работа некоторых присущих JavaScript объектов: строк, чисел и массивов.
В JavaScript строка является любым фрагментом текста. Как и многие другие объекты в JavaScript, строки можно определять несколькими различными способами:
var myString = 'Hello, World!'; var myString = new String('Hello, World!');
Первый метод используется наиболее часто. Второй метод применяется редко и только для гарантии, что получаемый объект является строкой. Например:
var n = 5; var s = new String(n*20);
В этом примере s будет строкой "100". Если просто задать s как n*20, то s будет содержать число 100. Однако поскольку JavaScript является слабо типизированным языком, то эти различия не будут существенно влиять на то, что вы делаете.
Строковые объекты (var n = new String('Hello World')) технически являются в Internet Explorer более медленными при некоторых операциях, чем строковые литералы (var n = 'Hello World'). Однако это поведение совершенно противоположно в других браузерах. В любом браузере различие редко бывает настолько заметно, чтобы об этом беспокоиться.
Единственное важное различие состоит в том, что eval() не работает со строковыми объектами.
Что, если в строке имеется апостроф? Следующий код работать не будет:
var n = 'The dog took it's bone outside';
Легко видеть, что апостроф в "it's " заканчивает строку. Поэтому мы получаем строку "The dog took it ", за которой следует " s bone outside' ". Это продолжение само по себе не является допустимым кодом JavaScript (или правильным грамматически, если на то пошло), поэтому будет получена ошибка.
Здесь можно сделать две вещи. Так как строка определяется с помощью одиночных или двойных кавычек, то можно задать строку с помощью двойных кавычек. Другая возможность состоит в экранировании апострофа. Чтобы экранировать символ, необходимо просто подставить перед ним символ . Символ в этом контексте сообщает JavaScript, что следующий символ необходимо воспринимать в точности так, как он есть, в номинальном значении, а не как специальный символ.
var n = "The dog took it's bone outside"; var n = 'The dog took it's bone outside';
Если в строке должен присутствовать символ , то он экранируется таким же образом: '\'.
В предыдущей лекции мы встречались с функциями indexOf и lastIndexOf. Напомним, что они делают. Функция indexOf возвращает число, определяющее первую позицию одной строки в другой. Если разыскиваемая строка не существует, то indexOf возвращает -1. Функция lastIndexOf идентична indexOf, но возвращает не первую позицию вхождения строки, а последнюю.
Тот факт, что функции indexOf и lastIndexOf возвращают -1, если строка не существует, является очень полезным и позволяет использовать эти функции для достаточно распространенной задачи - проверки того, что одна строка существует внутри другой.
Существует несколько других полезных функций для работы со строками, которые мы перечислим и кратко поясним.
[x]. charAt() сообщает, какой символ находится в определенной позиции строки. Поэтому 'Test'.charAt(1) = 'e'.
[x]. length сообщает длину строки . 'Test'.length = 4.
[x]. substring() выдает строку между двумя индексами. 'Test'.substring(1, 2) = 'e'.
[x]. substr() аналогична substring(), только второе число является не индексом, а длиной возвращаемой строки. Если это число указывает на позицию за пределами строки, то substr() вернет существующую часть строки. 'Test'.substr(1, 2) = 'es';
[x]. toLowerCase() и toUpperCase() делают то, что обозначают: преобразуют строку в нижний или верхний регистр символов соответственно. 'Test'.toUpperCase() = 'TEST';
Примеры всех приведенных выше функций:
alert('This is a Test'.indexOf('T')); // 0 alert('This is a Test'.lastIndexOf('T')); // 10 alert('This is a Test'.charAt(5)); // i alert('This is a Test'.length); // 14 alert('This is a Test'.substring(5, 9)); // is a alert('This is a Test'.substr(5, 9)); // is a Test alert('This is a Test'.toUpperCase()); // THIS IS A TEST alert('This is a Test'.toLowerCase()); // this is a test
Последней строковой функцией, которая будет рассмотрена, является eval(). eval() получает строку и выполняет строку, как если бы это был код JavaScript.
eval("alert('Hello, World!')");
В этом примере будет выведено сообщение "Hello, World!", как если бы функция alert была написана обычным образом. Это может быть очень полезно, так как позволяет создать содержащую код строку, а затем ее выполнить.
Работа с числами в JavaScript происходит достаточно просто. В лекциях 1 и 2 было показано, как выполняются базовые арифметические операции, операторы ++ , --, а также *=, +=, /= и -=. Мы узнали, что NaN означает "Не число" и что делает функция isNaN(). Осталось рассмотреть еще только несколько вещей.
Объект Math в JavaScript содержит функции, позволяющие сделать почти все, что можно сделать с числами помимо обычной арифметики. Math.PI, например, содержит просто число 3.141592653589793. В нем содержатся тригонометрические функции (sin, cos, tan, и т.д.), функции для округления чисел (Math.floor возвращает число, округленное с недостатком, Math.ceil возвращает число, округленное с избытком, а Math.round округляет число "нормально") и многие другие. Существует очень много функций, объяснять которые здесь не имеет смысла. Их всегда можно найти в подходящем справочнике. (Например, http://www.devguru.com/technologies/javascript/10734.asp)