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

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

const myVariable = function() { };

Затем вы можете вызвать эти функциональные выражения, используя идентификатор переменной:

const myVariable = function() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

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

const myVariable = function myFunction() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

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

const myVariable = function myFunction() {
  console.log( `I'm a ${ typeof myFunction }.`);
};

typeof myFunction;
> "undefined"

typeof myVariable;
> "function"

myVariable();
> "I'm a function."

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

const myVariable = function myFunction() {
    console.log( "One second elapsed." );
    setTimeout( myFunction, 1000 );
};

setTimeout( myVariable, 1000 );
> "One second elapsed."
> "One second elapsed."
> "One second elapsed."

Выражения стрелочных функций

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

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

const myFunction = () => {};

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

const myFunction = myParameter => {};

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

const myFunction = () => 2 + 2

myFunction()
> 4

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

function myParentFunction() {
    this.myProperty = true;
    let myFunction = () => {
            console.log( this );
    }
    myFunction();
};

let myInstance = new myParentFunction();
> Object { myProperty: true }

Вызов стрелочных функций

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

function myFunction() {
    let myArrowFunction = () => {
            console.log( arguments[ 0 ] );
    }
    myArrowFunction( true );
};

myFunction( false );
> false

В этом примере внешняя функция, вызываемая с аргументом false вызывает внутреннюю стрелочную функцию с аргументом true . Поскольку объект arguments внутри функции стрелки разрешается в привязку во внешней функции, внутренняя функция регистрирует false внешней функции.

Если нет объекта arguments , который можно было бы наследовать из родительского контекста, объект arguments стрелочной функции не определен, и попытка доступа к нему вызывает ошибку:

let myArrowFunction = () => {
    console.log(arguments);
};
myArrowFunction( true );
> Uncaught ReferenceError: arguments is not defined

Выражения с немедленным вызовом функций (IIFE)

Выражение немедленно вызываемой функции (IIFE), также иногда называемое «самовыполняющейся анонимной функцией», представляет собой функциональное выражение, которое вызывается немедленно после его определения. IIFE использует функциональное выражение, созданное путем включения функции в оператор группировки . Затем вторая совпавшая пара круглых скобок вызывает функцию либо сразу после самого определения функции, либо сразу после оператора группировки. Если вы используете стандартную функцию, между этими двумя подходами нет практической разницы:

(function() {
    console.log( "IIFE.")
    }
)();
> "IIFE."

(function() {
    console.log( "IIFE.")
    }
());
> "IIFE."

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

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

( () => {
    console.log( "IIFE." );
}() );
> Uncaught SyntaxError: missing ) in parenthetical

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

( () => {
    console.log( "IIFE." );
} )();
> "IIFE."

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

Проверьте свое понимание

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

Да
Нет