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

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

Функция - это блок кода, имеющий имя и выполняющийся при вызове функции.

Замечательно то, что функция НЕ выполнится, если не будет вызвана.

Записываются функции в общем виде следующем виде:

К именам функций существуют те же требования, что и к именам переменных. Важно помнить, что функция - это особый вид переменных в JavaScript, поэтому задавать одинаковые имена для функции и для переменной НЕЛЬЗЯ.

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

В JavaScript принято сначала объявлять функцию, а потом уже ее вызывать.

Обязательны и круглые скобки после имени функции. Они могут оставаться пустыми, а могут содержать аргументы функции. Например, функция выводит нам приветствие в диалоговом окне alert():

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

Что можно записывать в функциях JavaScript

Функции в своем коде могут иметь различные конструкции, характерные для языка JavaScript:

  • объявление переменных (var, let, const);
  • арифметические операции (сложение, вычитание и т.д.);
  • условные конструкции - if...else, switch...case, тернарный оператор;
  • любые виды циклов - for(), while(), do...while(), for...in;
  • вызов других функций.

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

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

В функции использована условная конструкция if...else и тернарный оператор.

Оператор return

Оператор return позволяет вернуть значение из функции, т.е. получить результат для дальнейшего использования в коде. Этот результат можно записать (присвоить) в какую-либо переменную, использовать в дальнейшем коде для вычислений, например, или вывести на html-страницу.

С помощью return можно возвращать логические значения (true или false), результат вычислений (число), строку или даже объект. Следует понимать 2 особенности, связанные  с этим оператором:

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

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

Рассмотрим пример посложнее. Нам необходимо создать объект на html-странице, причем не один, а несколько (в примере будет 2 - div и абзац). Выполняться это будет в функции. Затем в основном коде для каждого из элементов задается класс, описанный в стилях.

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

Примечание: данный скрипт должен быть размещен в body, и перед тегом <script> должен быть создан <div id="test"></div>

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

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

Здесь оператор "+" преобразует строку в число, если строка вида "12", "-14" и т.д. В случае строки "abcd12" происходит преобразование в тип NaN (Not a Number) и вычисление суммы не выполняется. Выводится сообщение об ошибке и возвращается 0 (ноль). Обратите внимание, что после оператора return выполнение функции прекращается.

Кстати, функция, которая не имеет оператора return, на самом деле возвращает значение undefined.

Аргументы функций в Javascript. Свойство функции arguments

В JavaScript существует псевдомассив аргументов функции, который так и называется - arguments. И, если точное количество аргументов неизвестно, то можно воспользоваться этим массивом. Он имеет свойство length, как и обычные массивы, но методы массивов push(), pop() и т.д. вы к нему применить не сможете.

Рассмотрим использование этого массива на примере функции суммы:

Параметры по умолчанию в функции

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

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

В первой строчке  сценария функции мы проверяем, а существует ли значение для переменной row, и если она равна undefined, т.е. значения нет, то присваиваем ей значение 2.  Во второй строке можно присвоить переменной cols одно из значений - либо переданное в функцию, либо, если параметр не был передан, т.е. он равен undefined, мы назначаем опять-таки значение 2.

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

Типы функций в Javascript

Все функции, которые мы рассматривали до сих пор, относятся к категории  Function Declaration, т.е. функции объявленной. Кроме того, существует  тип функций Function Expression, т.е. функции-выражения, или функциональные выражения. Посмотрите на разницу между их объявлением:

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

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

Для того чтобы увидеть ошибку, нужно открыть консоль браузера (F12 и Esc).

Так вот в этом простом примере мы не увидели второго окна alert(), т.к. функция func_expression() была вызвана ДО ее объявления. И это вызвало ошибку интерпретатора, т.к. Function expression НЕ вычисляется до выполнения javascript, из-за того, что является операцией присваивания переменной. Поэтому вызов function expression нельзя осуществлять до объявления самой функции, так как переменная на тот момент содержит undefined. Именно поэтому хорошим стилем кода на JavaScript является объявление всех функций в верхней части скрипта.

Что же касается Function declaration, то Javascript выявляет все определения таких функций и переносит их в начало сценария (этот процесс называется hoisting, или поднятие функций). Т.е. если в коде присутствуют такие функции, то JavaScript знает о них еще до выполнения сценария. Именно поэтому не важно, в каком месте кода вызывается Function declaration. Но все-таки, если есть возможность, объявляйте функции в начале сценария.

Области видимости переменных

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

В примере ниже глобальная переменная a перезаписывается внутри функции func(), а затем и во внутренней функции innerFunc(). А это далеко не всегда приводит к нужным результатам в процессе выполнения кода.

Если закомментировать вызов функции console.log() в каждой из функций, можно увидеть, чему будет равно значение переменной a. На данный момент будут выведено 3 числа последовательно: 1, 5 и 20.

Рекурсия

Рекурсия, или рекурсивная функция - это функция, которая вызывает сама себя до определенного момента. Этот момент определяется неким условием, после которого из функции, как правило, возвращается результат.

Классический пример рекурсии - это вычисление чисел Фибоначчи. Что это такое? Это последовательность чисел 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711 и т.п., в которой первые два числа равны либо 1 и 1, либо 0 и 1, а каждое последующее число равно сумме двух предыдущих чисел. Названы в честь средневекового математика Леонардо Пизанского, известного как Фибоначчи. Эту последовательность с помощью рекурсии вычисляют так (используем if):

или с помощью тернарного оператора:

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

Давайте рассмотрим еще один пример с возведением числа в степень. Напомню, что возведение в степень - это фактически умножение числа на само себя несколько раз. По правилам  математики, если мы возводим в нулевую степень, то любое число превратится в 1 (360 = 1). Число же в степени 1 - это всегда то же самое число, т.е. 51 = 5. Отсюда и ряд условий, проверяемых в функции.

Давайте начнем не с рекурсии, а с функции, которая основана на использовании цикла while, чтобы понимать механизм формирования условий:

На скриншоте видно, как проводятся вычисления в функции, если число, переданное в нее не равно 1 или степень не равна 0 или 1. Вычисления производятся только там, где нужно число возводить в степень, большую, чем 0 или 1.
Возведение в степень с помощью цикла while

Теперь перепишем эту функцию, используя рекурсию. Как правило, рекурсия использует довольно краткую запись кода, поэтому вместо if мы будем применять тернарный оператор с несколькими условиями: сначала проверим, не равно ли число 1, затем не равна ли степень 0, затем не равна ли степень 1, и только в случае не выполнения всех условий будем снова вызывать функцию для нашего числа, но со значением степени, уменьшенным на 1.

В коде специально использован console.log(res) для вывода результата при каждом вызове функции, поэтому вычисления будут подобны предыдущим.

Возведение в степень с помощью рекурсии

Сократим код рекурсии, убрав лишние переменные и console.log() и получим такой вариант:

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

Отдельным блоком среди остальных функций выделяются Стрелочные функции в ES6 - у них есть свои особенности и отличия от принятых в более ранних стандартах EcmaScript. Поскольку они поддерживаются всеми современными браузерами, стоит разобраться с синтаксисом стрелочных функций и областью их применения.

В функциях, которые применяются в JavaScript, существует ряд особенностей. Например, есть такое понятие, как hoisting - всплытие функций, объявленных в виде Function Declaration. Довольно часто используются callback-и - функции обратного вызова, а также  замыкания - особая область использования внутренних переменных в функциях. Прочитать об этом подробней можно в статье "Функции в JavaScript. Особенности использования".

Также у функций есть 3 специальных метода: bind(), call() и apply(), которые позволяют управлять контекстом вызова функции - ключевым словом this.

Автор: Админ

7 комментариев

  1. Хотелось бы еще насчет стрелочных функций получить информацию

  2. Планируется ли материал по стрелочным функциям из нового стандарта?

    • Планируется. Но точную дату сообщить пока не могу.

  3. Хотелось бы еще каких-то примеров, может, более сложных.

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

    • Спасибо! Материал планируется.
      Но на данный момент очень мало времени на подготовку публикаций.
      Поэтому будет примерно через месяц, не ранее.

  5. А более сложное использование функций будет.,
    Про замыкания, например?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *