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

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

Особенности Функций в JavaScript

» » Сообщение:

Функция - это значение

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

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

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

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

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

Код: Выделить всё Развернуть
function foo() {
  var x = "hello<br>";
  document.write(x);
}
 
var myfunc = foo;   // Присваивает ссылку на ту же самую функцию
 
myfunc();  //выводит "hello"
foo();     //делает тоже самое

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

Код: Выделить всё Развернуть
// Интерпретатор автоматически создаёт переменную с именем foo
function foo() {}
 
// Тоже самое, что и foo = 3, т. е. переменной foo просто присваивается новое значение
var foo = 3;       
 
document.write(foo);  // 3

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

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

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

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

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

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

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

Код: Выделить всё Развернуть
var foo = function(str) {  //переменной присваивается функция без имени
  document.write(str);
}
 
foo("JavaScript");

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

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

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

Код: Выделить всё Развернуть
sayName("Пётр"); // Будет ошибка
 
var sayName = function(name) {
  alert( "Меня зовут " + name );
};

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

Код: Выделить всё Развернуть
var x = 10;
 
if(x > 10) {
  var foo = function() { document.write("x больше 10"); }
} else {
  var foo = function() { document.write("x меньше 10"); }
}
 
foo();

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

Сравнение Function Expression с Function Declaration

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

Функция обратного вызова

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

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

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

Код: Выделить всё Развернуть
function foo(callback) { return callback(); }

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

Замыкания

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

Код: Выделить всё Развернуть
function sayHi(greeting) {
  return function (name) {        // Возвращает вложенную функцию
    alert(greeting +" "+ name); // greeting — ссылка на локальную переменную внешней функции
  }
}
 
var eng = sayHi("Hello");     // Переменная greeting теперь имеет значение "Hello"
var rus = sayHi("Привет, ");  // Переменная greeting теперь имеет значение "Привет, "
 
eng("John");     // "Hello John"
rus("Василий");  // "Привет, Василий"

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

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

Код: Выделить всё Развернуть
var i = 5;
function plusOne() {
  i++;
  return i;
}
 
alert(plusOne());
alert(plusOne());

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

Рекурсия

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

Код: Выделить всё Развернуть
// Функция возведения числа в степень
function power(num, exp) {
  if (exp == 0)      // Условие остановки рекурсии, если его не указать,
    return 1;        // функция будет выполняться бесконечно
  return num * power(num, exp - 1);
}
 
alert(power(2, 2));  // 4
Вложения
Зарегистрируйтесь, чтобы скачать вложения.
рекурсия, замыкания, function expression, function declaration, function



Похожие темыКомментарии ПросмотрыПоследнее сообщение
0889JavaScript. Логические операторы и ...
Сообщение от: Admin
0941Обход child nodes - потомков элемен...
Сообщение от: Admin
0663Колонки одинаковой высоты - лучшее ...
Сообщение от: Admin
151523Re: Рейтинг материалов +/- (плюс/ми...
Сообщение от: kinouser
0867Javascript Math.random(), аналог PH...
Сообщение от: Admin