Особенности Функций в JavaScript. Анонимные функции. Рекурсивные функции. Замыкания

Особенности Функций в JavaScript. Анонимные функции. Рекурсивные функции. Замыкания

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

Рассмотрим простой пример:

Код: Выделить всё Развернуть function foo() document.write(foo); //покажет код функции

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

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

var myfunc = foo; // Присваивает ссылку на ту же самую функцию

myfunc(); //выводит "hello"foo(); //делает тоже самое

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

Код: Выделить всё Развернуть // Интерпретатор автоматически создаёт переменную с именем foofunction foo()

// Тоже самое, что и foo = 3, т. е. переменной foo просто присваивается новое значениеvar foo = 3;

Анонимная функция

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

Функция-выражение определяется с помощью ключевого слова function, за которым указываются следующие компоненты:

  • Необязательный идентификатор, определяющий имя функции. Данное имя впоследствии может быть использовано для вызова внутри функции самой себя.
  • Пара круглых скобок вокруг списка из нуля или более параметров, разделяемых запятыми.
  • Тело функции, состоящее из пары фигурных скобок внутри которых располагаются инструкции.

Синтаксис функции-выражения выглядит следующим образом:

Код: Выделить всё Развернуть var f = function необязательное_имя(параметры) ;

Простой пример функции-выражения:

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

Функция определяемая в качестве функции-выражения, в спецификации языка, называется «Function Expression» (сокращенно FE).

В отличие от FD, определения FE не поднимаются вверх, поэтому их нельзя вызывать до того момента, пока интерпретатор не достиг строки с определением функции:

var sayName = function(name) ;

FE в отличие от FD, можно определять в if, так как FE создается только в тот момент, когда интерпретатор достигает строки с функцией:

Почему Function Declaration не работает в if?Ответ достаточно прост, потому что if может содержать только инструкции, а FD таковой не является.

Сравнение Function Expression с Function Declaration Действие Function Expression Function Declaration Создание функции: На этапе исполнения кода, т. е. в тот момент, когда управление достигает строки с функцией. До выполнения первой строки кода. Вызов до определения: Нет Да Вызов на месте: Да Нет Возможность определения в if: Да Нет Функция обратного вызова

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

Функции обратного вызова широко используются например в качестве обработчиков событий.

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

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

Замыкания

Замыкание (closure) - это вложенная функция, которая содержит ссылки на локальные переменные вмещающей ее функции (внешней). Чтобы стало понятнее, рассмотрим небольшой пример:

Код: Выделить всё Развернуть function sayHi(greeting) >

var eng = sayHi("Hello"); // Переменная greeting теперь имеет значение "Hello"var rus = sayHi("Привет, "); // Переменная greeting теперь имеет значение "Привет, "

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

Рассмотрим еще такой пример:

Тут, наверное, никого не смущает, что функция plusOne() имеет доступ к глобальной переменной i.А ведь это тоже замыкание, только по глобальной области видимости. Переменные же, объявленные внутри функций, имеют область видимости, ограниченную рамками этой функции, и замыкание происходит именно по ней - пусть даже и сама внешняя функция завершена.

Рекурсия

Рекурсивной функцией обычно называют функцию, которая вызывает сама себя:

Код: Выделить всё Развернуть // Функция возведения числа в степеньfunction power(num, exp)

📎📎📎📎📎📎📎📎📎📎