JavaScript с нуля — страница 3 из 30

До сих пор весь написанный нами код не имел никакой структуры и был простым до безобразия:

alert("hello, world!");

С таким кодом все в порядке, особенно учитывая, что он состоит из единственной инструкции. Но в реальном мире нам не отделаться так легко и код, написанный на JavaScript под настоящие задачи в жизни, редко будет таким простым.

Предположим, что нужно отобразить расстояние, пройденное объектом (рис. 3.1).

Рис. 3.1. Пройденное расстояние

Как вы помните еще со школы, чтобы вычислить расстояние, нужно скорость объекта умножить на время его движения (рис. 3.2).


расстояние = скорость × время


Рис. 3.2. Вычисление расстояния

Версия этого выражения на JavaScript будет выглядеть примерно так:

let speed = 10;

let time = 5;

alert(speed * time);

У нас есть две переменные, обозначенные как скорость (speed) и время (time), каждая из которых содержит число. Функция alert отображает результат умножения значений, содержащихся в переменных speed и time. Это весьма буквальная интерпретация уравнения для вычисления расстояния, которое мы только что рассмотрели.

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

let speed = 10;

let time = 5;

alert(speed * time);


let speed1 = 85;

let time1 = 1.5;

alert(speed1 * time1);


let speed2 = 12;

let time2 = 9;

alert(speed2 * time2);


let speed3 = 42;

let time3 = 21;

alert(speed3 * time3);

Не знаю, как вам, но по мне — это полная печалька. Наш код слишком многословный и повторяющийся. Мы уже видели ранее при изучении темы переменных, что повторение не позволяет создавать легкий в сопровождении код и отнимает время.

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

function showDistance(speed, time) {

alert(speed * time);

}


showDistance(10, 5);

showDistance(85, 1.5);

showDistance(12, 9);

showDistance(42, 21);

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

Поехали!

Что такое функция?

На самом базовом уровне функция — не более чем оболочка для некоего кода.

По сути функция:

• группирует инструкции;

• позволяет использовать код многократно.

Вы редко напишете или воспользуетесь кодом, в котором не будет функций, поэтому важно не только ознакомиться с ними, но и разобраться в тонкостях их правильной работы.

Простая функция

Лучший способ понять функции — это погрузиться в них и начать использовать. Поэтому создадим для начала самую простую функцию. Это не особо увлекательный процесс. Требуется лишь понимание некоторых особенностей синтаксиса вроде использования причудливых фигурных скобок и их собратьев.

Ниже приведен пример того, как выглядит простая функция:

function sayHello() {

alert("hello!");

}

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

function sayHello() {

alert("hello!");

}

sayHello();

Чтобы попрактиковаться, создайте новый HTML-документ (назовите его functions_sayhello.htm):


Say Hello!




Если вы наберете этот текст полностью и просмотрите страницу в браузере, то увидите, как отобразится hello!. Это нужно сделать, чтобы убедиться, что наш код работает. Далее разберем, почему этот код сработал, а для этого разобьем функцию sayHello на несколько самостоятельных фрагментов и рассмотрим каждый из них подробнее.

Во-первых, мы видим ключевое слово function (рис. 3.3).


function sayHello() {

alert("hello!");

}


Рис. 3.3. Ключевое слово function

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

После ключевого слова function мы указываем актуальное имя функции и ставим после него открывающую и закрывающую скобки (), как показано на рис. 3.4.


function sayHello() {

alert("hello!");

}


Рис. 3.4. Имя функции и скобки

Завершая процесс объявления функции, нужно поставить открывающую и закрывающую фигурные скобки, внутри которых указываются нужные инструкции (рис. 3.5).


function sayHello() {

alert("hello!");

}


Рис. 3.5. Открывающая и закрывающая фигурные скобки

В заключение рассмотрим содержимое функции, а именно те инструкции, которые задают функциональность (рис. 3.6).


function sayHello() {

alert("hello!");

}


Рис. 3.6. Содержимое функции

В нашем примере содержимым является функция alert, отображающая диалоговое окно со словом hello!.

Последнее, что осталось рассмотреть, — это вызов функции (рис. 3.7).


function sayHello() {

alert("hello!");

}

sayHello();


Рис. 3.7. Вызов функции

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

Вот мы и рассмотрели простейшую функцию. Далее, с опорой на только что пройденный материал, мы ознакомимся с более жизненными примерами функций.

Создание функции, принимающей аргументы

Предыдущий пример с sayHello слишком прост:

function sayHello() {

alert("hello!");

}

sayHello();

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

Начнем с простого и знакомого примера:

alert("my argument");

Перед нами функция alert. Вероятно, мы уже видели ее пару-тройку (или несколько десятков) раз. Суть в том, что в эту функцию передается так называемый аргумент, который описывает то, что требуется отобразить при вызове. На рис. 3.8 показано, что отобразится на экране, если вызвать функцию alert с аргументом myargument.

Аргумент — это то, что находится между открывающими и закрывающими скобками. Функция alert — лишь одна из множества возможных функций, принимающих аргументы. Многие из функций, которые вы создадите в будущем, будут также принимать аргументы.

В этой главе мы рассматривали еще одну функцию, принимающую аргументы, а именно showDistance:

function showDistance(speed, time) {

alert(speed * time);

}

Рис. 3.8. Отображение аргумента

Понять, что функция принимает аргументы, можно, просто взглянув на ее описание (объявление):

function showDistance(speed, time) {

alert(speed * time);

}

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

В случае с showDistance можно сделать вывод о том, что эта функция принимает два аргумента. Первый из них соответствует speed (скорости), а второй — time (времени).

Мы задаем значения аргументов в рамках вызова функции:

function showDistance (speed, time) {

alert(speed * time);

}

showDistance(10, 5);

В нашем случае мы вызываем функцию showDistance и задаем значения, которые хотим в нее передать, внутри скобок (рис. 3.9).

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


showDistance(10, 5);


Рис. 3.9. Значения, которые мы хотим передать в функцию

Давайте рассмотрим этот процесс подробнее и начнем с диаграммы на рис. 3.10.

Рис. 3.10. Диаграмма вызова функции

Для вызова в функцию showDistance передается 10 как аргумент для speed и 5 — для time. Изображенный на диаграмме перенос полностью основан на последовательности.

Как только передаваемые значения достигают функции, определенные для аргументов имена начинают обрабатываться как имена переменных (рис. 3.11).

Рис. 3.11. Имена аргументов работают как переменные

Мы можем использовать эти имена переменных, чтобы легко и без забот ссылаться на значения, содержащиеся в аргументах внутри функции.

Несоответствие числа аргументов

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

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

Создание функции, возвращающей результат

Последний вид функции, который мы рассмотрим, — это та функция, которая возвращает результат в ответ на вызов. Вот, что нам нужно сделать. У нас есть функция showDistance, которая, как нам прекрасно известно, выглядит так:

function showDistance(speed, time) {

alert(speed * time);

}

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

let myDistance = showDistance(10, 5);

Переменная myDistance будет содержать результат вычисления, которое выполнит функция showDistance.

Ключевое слово return

Возврат данных из функции производится посредством ключевого слова return. Давайте создадим новую функцию с именем getDistance, которая будет выглядеть как showDistance, но отличаться в том, что происходит при выполнении функции до завершения:

function getDistance(speed, time) {

let distance = speed * time;

return distance;

}

Обратите внимание, что мы вычисляем расстояние, умножая speed на time. Вместо отображения уведомления (alert) мы возвращаем значение расстояния (которое содержится в переменной distance).

Мы можем выполнить вызов функции getDistance в рамках инициализации переменной:

let myDistance = getDistance(10, 5);

Когда функция getDistance будет вызвана, она выполнит вычисление и вернет численное значение, которое затем будет присвоено переменной myDistance. И всего делов-то!

Ранний выход из функции

Как только функция доходит до ключевого слова return, она прекращает выполнять обработку, которую делала до этого момента, возвращает значение, заданное в вызывающей функции (caller), и производит выход:

function getDistance(speed, time) {

let distance = speed * time;

return distance;


if (speed < 0) {

distance *= -1;

}

}

Любой код, прописанный после инструкции return, не будет обработан. Эта часть будет проигнорирована, как если бы ее и не было вовсе.

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

function doSomething() {

let foo = "Nothing interesting";

return;

}

Использовать ключевое слово return для возвращения результата не обязательно. Оно может использоваться отдельно, как мы увидели в примере выше, просто для выхода из функции. Если значение return не задано функцией, возвращается значение по умолчанию, undefined.

КОРОТКО О ГЛАВНОМ

Функции относятся к тому небольшому числу компонентов, которые вы будете использовать практически в каждом приложении JavaScript. Они предоставляют востребованную возможность — создавать переиспользуемый код. Не важно, используете ли вы собственные функции или те, что встроены в JavaScript, — вы просто не сможете обойтись без них.

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

Если у вас есть вопросы по пройденной теме — добро пожаловать на форум https://forum.kirupa.com, где я или другие смышленые веб-разработчики поможем вам.

Глава 4. Условные обозначения: if…else и switch