Какое действие не характеризует первоклассное выражение javascript
Перейти к содержимому

Какое действие не характеризует первоклассное выражение javascript

  • автор:

Функциональные выражения

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/function-expressions.

В JavaScript функция является значением, таким же как строка или число.

Как и любое значение, объявленную функцию можно вывести, вот так:

function sayHi() < alert( "Привет" ); >alert( sayHi ); // выведет код функции

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

Функцию можно скопировать в другую переменную:

function sayHi() < // (1) alert( "Привет" ); >var func = sayHi; // (2) func(); // Привет // (3) sayHi = null; sayHi(); // ошибка (4)
  1. Объявление (1) как бы говорит интерпретатору «создай функцию и помести её в переменную sayHi
  2. В строке (2) мы копируем функцию в новую переменную func . Ещё раз обратите внимание: после sayHi нет скобок. Если бы они были, то вызов var func = sayHi() записал бы в func результат работы sayHi() (кстати, чему он равен? правильно, undefined , ведь внутри sayHi нет return ).
  3. На момент (3) функцию можно вызывать и как sayHi() и как func()
  4. …Однако, в любой момент значение переменной можно поменять. При этом, если оно не функция, то вызов (4) выдаст ошибку.

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

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

Объявление Function Expression

Существует альтернативный синтаксис для объявления функции, который ещё более наглядно показывает, что функция – это всего лишь разновидность значения переменной.

Он называется «Function Expression» (функциональное выражение) и выглядит так:

var f = function(параметры) < // тело функции >;
var sayHi = function(person) < alert( "Привет, " + person ); >; sayHi('Вася');

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

«Классическое» объявление функции, о котором мы говорили до этого, вида function имя(параметры) <. >, называется в спецификации языка «Function Declaration».

  • Function Declaration – функция, объявленная в основном потоке кода.
  • Function Expression – объявление функции в контексте какого-либо выражения, например присваивания.

Несмотря на немного разный вид, по сути две эти записи делают одно и то же:

// Function Declaration function sum(a, b) < return a + b; >// Function Expression var sum = function(a, b)

Оба этих объявления говорят интерпретатору: «объяви переменную sum , создай функцию с указанными параметрами и кодом и сохрани её в sum «.

Основное отличие между ними: функции, объявленные как Function Declaration, создаются интерпретатором до выполнения кода.

Поэтому их можно вызвать до объявления, например:

sayHi("Вася"); // Привет, Вася function sayHi(name)

А если бы это было объявление Function Expression, то такой вызов бы не сработал:

sayHi("Вася"); // ошибка! var sayHi = function(name)

Это из-за того, что JavaScript перед запуском кода ищет в нём Function Declaration (их легко найти: они не являются частью выражений и начинаются со слова function ) и обрабатывает их.

А Function Expression создаются в процессе выполнения выражения, в котором созданы, в данном случае – функция будет создана при операции присваивания sayHi = function.

Как правило, возможность Function Declaration вызвать функцию до объявления – это удобно, так как даёт больше свободы в том, как организовать свой код.

Можно расположить функции внизу, а их вызов – сверху или наоборот.

Условное объявление функции

В некоторых случаях «дополнительное удобство» Function Declaration может сослужить плохую службу.

Например, попробуем, в зависимости от условия, объявить функцию sayHi по-разному:

var age = +prompt("Сколько вам лет?", 20); if (age >= 18) < function sayHi() < alert( 'Прошу вас!' ); >> else < function sayHi() < alert( 'До 18 нельзя' ); >> sayHi();

Function Declaration при use strict видны только внутри блока, в котором объявлены. Так как код в учебнике выполняется в режиме use strict , то будет ошибка.

А что, если использовать Function Expression?

var age = prompt('Сколько вам лет?'); var sayHi; if (age >= 18) < sayHi = function() < alert( 'Прошу Вас!' ); >> else < sayHi = function() < alert( 'До 18 нельзя' ); >> sayHi();
var age = prompt('Сколько вам лет?'); var sayHi = (age >= 18) ? function() < alert('Прошу Вас!'); >: function() < alert('До 18 нельзя'); >; sayHi();

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

Анонимные функции

Взглянем ещё на один пример – функцию ask(question, yes, no) с тремя параметрами:

question Строка-вопрос yes Функция no Функция

Она выводит вопрос на подтверждение question и, в зависимости от согласия пользователя, вызывает функцию yes() или no() :

function ask(question, yes, no) < if (confirm(question)) yes() else no(); >function showOk() < alert( "Вы согласились." ); >function showCancel() < alert( "Вы отменили выполнение." ); >// использование ask("Вы согласны?", showOk, showCancel);

Какой-то очень простой код, не правда ли? Зачем, вообще, может понадобиться такая ask ?

…Оказывается, при работе со страницей такие функции как раз очень востребованы, только вот спрашивают они не простым confirm , а выводят более красивое окно с вопросом и могут интеллектуально обработать ввод посетителя. Но это всё потом, когда перейдём к работе с интерфейсом.

Здесь же обратим внимание на то, что то же самое можно написать более коротко:

function ask(question, yes, no) < if (confirm(question)) yes() else no(); >ask( "Вы согласны?", function() < alert("Вы согласились."); >, function() < alert("Вы отменили выполнение."); >);

Здесь функции объявлены прямо внутри вызова ask(. ) , даже без присвоения им имени.

Функциональное выражение, которое не записывается в переменную, называют анонимной функцией.

Действительно, зачем нам записывать функцию в переменную, если мы не собираемся вызывать её ещё раз? Можно просто объявить непосредственно там, где функция нужна.

Такого рода код возникает естественно, он соответствует «духу» JavaScript.

new Function

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

Он позволяет создавать функцию полностью «на лету» из строки, вот так:

var sum = new Function('a,b', ' return a+b; '); var result = sum(1, 2); alert( result ); // 3

То есть, функция создаётся вызовом new Function(params, code) :

params Параметры функции через запятую в виде строки. code Код функции в виде строки.

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

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

Итого

Функции в JavaScript являются значениями. Их можно присваивать, передавать, создавать в любом месте кода.

  • Если функция объявлена в основном потоке кода, то это Function Declaration.
  • Если функция создана как часть выражения, то это Function Expression.

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

Function Declaration Function Expression
Время создания До выполнения первой строчки кода. Когда управление достигает строки с функцией.
Можно вызвать до объявления Да (т.к. создаётся заранее) Нет
Условное объявление в if Не работает Работает

Иногда в коде начинающих разработчиков можно увидеть много Function Expression. Почему-то, видимо, не очень понимая происходящее, функции решают создавать как var func = function() , но в большинстве случаев обычное объявление функции – лучше.

Если нет явной причины использовать Function Expression – предпочитайте Function Declaration.

Сравните по читаемости:

// Function Expression var f = function() < . >// Function Declaration function f()

Function Declaration короче и лучше читается. Дополнительный бонус – такие функции можно вызывать до того, как они объявлены.

Используйте Function Expression только там, где это действительно нужно и удобно.

Функции

Зачастую нам надо повторять одно и то же действие во многих частях программы.

Например, необходимо красиво вывести сообщение при приветствии посетителя, при выходе посетителя с сайта, ещё где-нибудь.

Чтобы не повторять один и тот же код во многих местах, придуманы функции. Функции являются основными «строительными блоками» программы.

Примеры встроенных функций вы уже видели – это alert(message) , prompt(message, default) и confirm(question) . Но можно создавать и свои.

Объявление функции

Для создания функций мы можем использовать объявление функции.

Пример объявления функции:

function showMessage()

Вначале идёт ключевое слово function , после него имя функции, затем список параметров в круглых скобках через запятую (в вышеприведённом примере он пустой) и, наконец, код функции, также называемый «телом функции», внутри фигурных скобок.

function имя(параметры)

Наша новая функция может быть вызвана по своему имени: showMessage() .

function showMessage() < alert( 'Всем привет!' ); >showMessage(); showMessage();

Вызов showMessage() выполняет код функции. Здесь мы увидим сообщение дважды.

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

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

Локальные переменные

Переменные, объявленные внутри функции, видны только внутри этой функции.

function showMessage() < let message = "Привет, я JavaScript!"; // локальная переменная alert( message ); >showMessage(); // Привет, я JavaScript! alert( message ); // 

Внешние переменные

У функции есть доступ к внешним переменным, например:

let userName = 'Вася'; function showMessage() < let message = 'Привет, ' + userName; alert(message); >showMessage(); // Привет, Вася

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

let userName = 'Вася'; function showMessage() < userName = "Петя"; // (1) изменяем значение внешней переменной let message = 'Привет, ' + userName; alert(message); >alert( userName ); // Вася перед вызовом функции showMessage(); alert( userName ); // Петя, значение внешней переменной было изменено функцией

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

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

let userName = 'Вася'; function showMessage() < let userName = "Петя"; // объявляем локальную переменную let message = 'Привет, ' + userName; // Петя alert(message); >// функция создаст и будет использовать свою собственную локальную переменную userName showMessage(); alert( userName ); // Вася, не изменилась, функция не трогала внешнюю переменную

Глобальные переменные

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

Глобальные переменные видимы для любой функции (если только их не перекрывают одноимённые локальные переменные).

Желательно сводить использование глобальных переменных к минимуму. В современном коде обычно мало или совсем нет глобальных переменных. Хотя они иногда полезны для хранения важнейших «общепроектовых» данных.

Параметры

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

В нижеприведённом примере функции передаются два параметра: from и text .

function showMessage(from, text) < // параметры: from, text alert(from + ': ' + text); >showMessage('Аня', 'Привет!'); // Аня: Привет! (*) showMessage('Аня', "Как дела?"); // Аня: Как дела? (**)

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

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

function showMessage(from, text) < from = '*' + from + '*'; // немного украсим "from" alert( from + ': ' + text ); >let from = "Аня"; showMessage(from, "Привет"); // *Аня*: Привет // значение "from" осталось прежним, функция изменила значение локальной переменной alert( from ); // Аня

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

  • Параметр – это переменная, указанная в круглых скобках в объявлении функции.
  • Аргумент – это значение, которое передаётся функции при её вызове.

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

Рассматривая приведённый выше пример, мы могли бы сказать: "функция showMessage объявляется с двумя параметрами, затем вызывается с двумя аргументами: from и "Привет" ".

Значения по умолчанию

Если при вызове функции аргумент не был указан, то его значением становится undefined .

Например, вышеупомянутая функция showMessage(from, text) может быть вызвана с одним аргументом:

showMessage("Аня");

Это не приведёт к ошибке. Такой вызов выведет "*Аня*: undefined" . В вызове не указан параметр text , поэтому предполагается, что text === undefined .

Если мы хотим задать параметру text значение по умолчанию, мы должны указать его после = :

function showMessage(from, text = "текст не добавлен") < alert( from + ": " + text ); >showMessage("Аня"); // Аня: текст не добавлен

Теперь, если параметр text не указан, его значением будет "текст не добавлен"

В данном случае "текст не добавлен" это строка, но на её месте могло бы быть и более сложное выражение, которое бы вычислялось и присваивалось при отсутствии параметра. Например:

function showMessage(from, text = anotherFunction()) < // anotherFunction() выполнится только если не передан text // результатом будет значение text >

Вычисление параметров по умолчанию

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

В приведённом выше примере, функция anotherFunction() не будет вызвана вообще, если указан аргумент text .

С другой стороны, функция будет независимо вызываться каждый раз, когда аргумент text отсутствует.

Использование параметров по умолчанию в ранних версиях JavaScript

Ранние версии JavaScript не поддерживали параметры по умолчанию. Поэтому существуют альтернативные способы, которые могут встречаться в старых скриптах.

Например, явная проверка на undefined :

function showMessage(from, text) < if (text === undefined) < text = 'текст не добавлен'; >alert( from + ": " + text ); >

…Или с помощью оператора || :

function showMessage(from, text) < // Если значение text ложно, тогда присвоить параметру text значение по умолчанию // заметим, что при этом пустая строка text === "" будет также считаться отсутствующим значением text = text || 'текст не добавлен'; . >

Альтернативные параметры по умолчанию

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

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

function showMessage(text) < // . if (text === undefined) < // если параметр отсутствует text = 'пустое сообщение'; >alert(text); > showMessage(); // пустое сообщение

…Или мы можем использовать оператор || :

function showMessage(text) < // если значение text ложно или равняется undefined, тогда присвоить text значение 'пусто' text = text || 'пусто'; . >

Современные движки JavaScript поддерживают оператор нулевого слияния ?? . Его использование будет лучшей практикой, в случае, если большинство ложных значений, таких как 0 , следует расценивать как «нормальные».

function showCount(count) < // если count равен undefined или null, показать "неизвестно" alert(count ?? "неизвестно"); >showCount(0); // 0 showCount(null); // неизвестно showCount(); // неизвестно

Возврат значения

Функция может вернуть результат, который будет передан в вызвавший её код.

Простейшим примером может служить функция сложения двух чисел:

function sum(a, b) < return a + b; >let result = sum(1, 2); alert( result ); // 3

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

Вызовов return может быть несколько, например:

function checkAge(age) < if (age >= 18) < return true; >else < return confirm('А родители разрешили?'); >> let age = prompt('Сколько вам лет?', 18); if ( checkAge(age) ) < alert( 'Доступ получен' ); >else

Возможно использовать return и без значения. Это приведёт к немедленному выходу из функции.

function showMovie(age) < if ( !checkAge(age) ) < return; >alert( "Вам показывается кино" ); // (*) // . >

В коде выше, если checkAge(age) вернёт false , showMovie не выполнит alert .

Результат функции с пустым return или без него – undefined

Если функция не возвращает значения, это всё равно, как если бы она возвращала undefined :

function doNothing() < /* пусто */ >alert( doNothing() === undefined ); // true

Пустой return аналогичен return undefined :

function doNothing() < return; >alert( doNothing() === undefined ); // true

Никогда не добавляйте перевод строки между return и его значением

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

return (some + long + expression + or + whatever * f(a) + f(b))

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

return; (some + long + expression + or + whatever * f(a) + f(b))

Таким образом, это фактически стало пустым return .

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

return ( some + long + expression + or + whatever * f(a) + f(b) )

И тогда всё сработает, как задумано.

Выбор имени функции

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

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

Например, функции, начинающиеся с "show" обычно что-то показывают.

Функции, начинающиеся с…

  • "get…" – возвращают значение,
  • "calc…" – что-то вычисляют,
  • "create…" – что-то создают,
  • "check…" – что-то проверяют и возвращают логическое значение, и т.д.

Примеры таких имён:

showMessage(..) // показывает сообщение getAge(..) // возвращает возраст (получая его каким-то образом) calcSum(..) // вычисляет сумму и возвращает результат createForm(..) // создаёт форму (и обычно возвращает её) checkPermission(..) // проверяет доступ, возвращая true/false

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

Одна функция – одно действие

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

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

Несколько примеров, которые нарушают это правило:

  • getAge – будет плохим выбором, если функция будет выводить alert с возрастом (должна только возвращать его).
  • createForm – будет плохим выбором, если функция будет изменять документ, добавляя форму в него (должна только создавать форму и возвращать её).
  • checkPermission – будет плохим выбором, если функция будет отображать сообщение с текстом доступ разрешён/запрещён (должна только выполнять проверку и возвращать её результат).

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

Сверхкороткие имена функций

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

Например, фреймворк jQuery определяет функцию с помощью $ . В библиотеке Lodash основная функция представлена именем _ .

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

Функции == Комментарии

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

Небольшие функции не только облегчают тестирование и отладку – само существование таких функций выполняет роль хороших комментариев!

Например, сравним ниже две функции showPrimes(n) . Каждая из них выводит простое число до n .

Первый вариант использует метку nextPrime :

function showPrimes(n) < nextPrime: for (let i = 2; i < n; i++) < for (let j = 2; j < i; j++) < if (i % j == 0) continue nextPrime; >alert( i ); // простое > >

Второй вариант использует дополнительную функцию isPrime(n) для проверки на простое:

function showPrimes(n) < for (let i = 2; i < n; i++) < if (!isPrime(i)) continue; alert(i); // простое >> function isPrime(n) < for (let i = 2; i < n; i++) < if ( n % i == 0) return false; >return true; >

Второй вариант легче для понимания, не правда ли? Вместо куска кода мы видим название действия ( isPrime ). Иногда разработчики называют такой код самодокументируемым.

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

Итого

Объявление функции имеет вид:

function имя(параметры, через, запятую) < /* тело, код функции */ >
  • Передаваемые значения копируются в параметры функции и становятся локальными переменными.
  • Функции имеют доступ к внешним переменным. Но это работает только изнутри наружу. Код вне функции не имеет доступа к её локальным переменным.
  • Функция может возвращать значение. Если этого не происходит, тогда результат равен undefined .

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

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

  • Имя функции должно понятно и чётко отражать, что она делает. Увидев её вызов в коде, вы должны тут же понимать, что она делает, и что возвращает.
  • Функция – это действие, поэтому её имя обычно является глаголом.
  • Есть много общепринятых префиксов, таких как: create… , show… , get… , check… и т.д. Пользуйтесь ими как подсказками, поясняющими, что делает функция.

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

Задачи

Обязателен ли "else"?

важность: 4

Следующая функция возвращает true , если параметр age больше 18 .

В ином случае она запрашивает подтверждение через confirm и возвращает его результат:

function checkAge(age) < if (age >18) < return true; >else < // . return confirm('Родители разрешили?'); >>

Будет ли эта функция работать как-то иначе, если убрать else ?

function checkAge(age) < if (age >18) < return true; >// . return confirm('Родители разрешили?'); >

Есть ли хоть одно отличие в поведении этого варианта?

Оба варианта функций работают одинаково, отличий нет.

Перепишите функцию, используя оператор '?' или '||'

важность: 4

Следующая функция возвращает true , если параметр age больше 18 .

В ином случае она задаёт вопрос confirm и возвращает его результат.

function checkAge(age) < if (age >18) < return true; >else < return confirm('Родители разрешили?'); >>

Перепишите функцию, чтобы она делала то же самое, но без if , в одну строку.

Сделайте два варианта функции checkAge :

  1. Используя оператор ?
  2. Используя оператор ||
function checkAge(age) < return (age >18) ? true : confirm('Родители разрешили?'); >

Используя оператор || (самый короткий вариант):

function checkAge(age) < return (age >18) || confirm('Родители разрешили?'); >

Обратите внимание, что круглые скобки вокруг age > 18 не обязательны. Они здесь для лучшей читаемости кода.

Анонимные функции в JS: правила вызова и область видимости

Используя конструкцию (function() <>)() , которую называют немедленно вызываемым функциональным выражением или IIFE (Immediately Invoked Function Expression), вы можете скрыть переменные и функции от глобальной области видимости.

Скопировать код

// Взаимодействие с анонимной функцией (function() < let secret = 'Тут холодно!'; // Заметка о погоде console.log(secret); // 'Тут холодно!' >)(); // Не получилось – 'secret' не найден в общем пространстве имен.

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

Магия функции

Важно ясно разделять объявления функций и функциональные выражения в JavaScript. Объявленные функции всплывают, а функциональные выражения – нет. Когда функцию окружают скобками () , она становится анонимной и может быть немедленно выполнена.

Скопировать код

// Это не только элегантно, но и практично. (function(message) < console.log(message); >)('Сообщение доставлено!');

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

Ни одно пространство имен не должно быть утеряно

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

Замыкание как тайный агент

Замыкания сохраняют секреты и работают более тихо, чем кажется.

Скопировать код

const secretAgent = (function() < let secretCounter = 0; const increaseBy = value =>secretCounter += value; return < increment: () =>increaseBy(1), decrement: () => increaseBy(-1), reveal: () => secretCounter >; >)(); // secretAgent.reveal() скрывает истинное значение.

Анонимность в роли невидимого героя

Анонимные функции часто используются в качестве аргументов, если фукнцию больше не предполагают использовать. Сокращая повторы, увеличиваем производительность!

Зона временной мертвоты и быстрый подъем!

IIFE воссоздаёт эффект блочной области видимости в JavaScript: заботливый покровительство до внедрения let и const в ES6.

Визуализация

В качестве примера немедленно вызываемой анонимной функции:

Функциональное выражение

Ключевое слово function может использоваться для определения функции внутри выражения.

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

Синтаксис

var myFunction = function [name]([param1[, param2[, . paramN]]]) < statements >;

С версии ES2015 можно также использовать стрелочные функции.

Параметры

Имя функции. Может быть опущено, в таком случае функция является анонимной. Имя функции является локальным для её тела.

Имя аргумента, передаваемого в функцию.

Инструкции, составляющие тело функции.

Описание

Функциональное выражение и объявление функции очень похожи и имеют почти одинаковый синтаксис. Главным отличием между ними является имя функции, которое в случае функциональных выражений может быть опущено для создания анонимных функций. Функциональное выражение может быть использовано для создания самовызывающейся функции IIFE (Immediately Invoked Function Expression), которая исполняется сразу же после того, как она была определена. Более подробная информация изложена в разделе о функциях.

Поднятие функциональных выражений

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

.log(notHoisted); // undefined //Хотя объявленная переменная и поднимается, определение переменной происходит позже notHoisted(); // TypeError: notHoisted is not a function var notHoisted = function ()  console.log("bar"); >; 

Именованное функциональное выражение

Если вы хотите сослаться на текущую функцию внутри тела этой функции, вам необходимо создать именованное функциональное выражение. Данное имя будет локальным только для тела функции (её области видимости). Кроме того, это позволяет избежать использования нестандартного свойства arguments.callee .

var math =  factit: function factorial(n)  console.log(n); if (n  1)  return 1; > return n * factorial(n - 1); >, >; math.factit(3); //3;2;1; 

Переменная, которой присвоено функциональное выражение, будет иметь свойство name , содержащее имя функции. Оно не изменится при переприсваивании другой переменной. Для анонимной функции, значением свойства name будет имя переменной (неявное имя). Если же имя задано, то будет использовано имя функции (явное имя). Это же касается стрелочных функций (в их случае там будет записано имя переменной, т.к. они всегда анонимные).

var foo = function () >; foo.name; // "foo" var foo2 = foo; foo2.name; // "foo" var bar = function baz() >; bar.name; // "baz" console.log(foo === foo2); // true console.log(typeof baz); // undefined console.log(bar === baz); // false (errors because baz == undefined) 

Примеры

Следующий пример демонстрирует создание безымянной (анонимной) функции и присвоение её переменной x . Функция возвращает квадрат переданного значения:

var x = function (y)  return y * y; >; 

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

.addEventListener("click", function (event)  console.log("button is clicked!"); >); 

Спецификации

Specification
ECMAScript Language Specification
# sec-function-definitions

Совместимость с браузерами

BCD tables only load in the browser

Смотрите также

  • Functions and function scope (en-US)
  • Function
  • function statement
  • function* statement
  • function* expression
  • GeneratorFunction

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

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