Expressões de função

As expressões de função são funções criadas onde uma expressão é esperada. Com frequência, você vai encontrar funções expressões como valores atribuídos a uma variável. Embora uma declaração de função sempre exija um nome, você pode usar expressões de função para criar funções anônimas omitindo o identificador e seguindo a palavra-chave function com um par de parênteses contendo parâmetros opcionais:

const myVariable = function() { };

Em seguida, chame essas expressões de função usando o identificador da variável:

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

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

Também é possível usar expressões de função para criar funções nomeadas usando uma sintaxe semelhantes às declarações de função:

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

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

No entanto, ao contrário das declarações de função, uma expressão de função nomeada pode ser acessado somente pelo nome da função dentro da própria função:

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

typeof myFunction;
> "undefined"

typeof myVariable;
> "function"

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

Nomes associados a expressões de função são úteis principalmente para depuração. Um uma expressão de função nomeada também pode se chamar recursivamente, embora essa não seja muito comum no desenvolvimento moderno:

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

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

Expressões de função de seta

As expressões de função de seta (geralmente chamadas de "funções de seta" ou, raramente, "funções lambda") foram introduzidas no ES6 para fornecer uma sintaxe concisa para criar expressões de função anônima com alguns comportamentos exclusivos.

Você pode criar uma arrow function sempre que uma expressão for esperada, por exemplo, como um valor atribuído a uma variável. Em sua forma mais comum, uma seta é composta de um par de parênteses correspondentes que contêm zero ou mais parâmetros, uma seta composta por um único sinal de igual e um caractere "maior que" (=>) e um par de chaves correspondentes contendo o corpo da função:

const myFunction = () => {};

Em determinadas condições, você pode tornar a sintaxe ainda mais compacta. Se você estiver usando apenas um parâmetro, você pode deixar de fora os parênteses iniciais:

const myFunction = myParameter => {};

Quando você quer que o corpo da função retorne o valor de uma única expressão, colocar o corpo da função entre chaves e não a palavra-chave return são obrigatórios:

const myFunction = () => 2 + 2

myFunction()
> 4

As funções de seta são únicas porque não têm contexto próprio para arguments ou this. Em vez disso, eles herdam da função de seta ambiente lexicamente incluído, o mais próximo função de inclusão que fornece esses contextos.

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

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

Chamar funções de seta

As funções de seta não vinculam argumentos da mesma forma que outros tipos de função. Um objeto arguments no corpo de uma arrow function herda o valor de a posição mais próxima da função de seta ambiente lexicamente incluído:

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

myFunction( false );
> false

Neste exemplo, uma função externa chamada com o argumento false chama uma função de seta interna com o argumento true. Como o objeto arguments dentro da arrow function se refere à vinculação na função externa, a a função interna registra o false da função externa.

Se não houver um objeto arguments para herdar do contexto pai, o objeto arguments da função de seta não será definido, e tentar acessá-lo causará um erro:

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

Expressões de função invocadas imediatamente (IIFE)

Uma expressão de função invocada imediatamente (IIFE, na sigla em inglês), também chamada de "função anônima autoexecutável", é uma expressão de função chamada imediatamente quando é definida. Um IIFE usa uma expressão de função criada pelo Colocar a função em um operador de agrupamento. Um segundo par de parênteses correspondente chama a função, imediatamente após a definição da função ou imediatamente após o operador de agrupamento. Se você usar uma função padrão, não haverá diferença prática entre as duas abordagens:

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

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

O primeiro exemplo chama a expressão de função agrupada. O segundo exemplo chama uma declaração de função dentro dos operadores de agrupamento, e o resultado final é então avaliada como uma expressão agrupada. O resultado é o mesmo em caso.

No entanto, há uma diferença quando o IIFE é uma função de seta. Neste caso, os parênteses usados para chamar a função devem estar fora do grupo operadores, porque uma arrow function por si só não é uma expressão, mas deve ser criada em um contexto em que uma expressão é esperada. Ao tentar chamar o método função de seta dentro do escopo dos operadores de agrupamento significaria chamar uma função de seta que ainda não foi criada no contexto de uma expressão:

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

Como os operadores de agrupamento esperam uma expressão, a função de seta dentro seja definida, permitindo que os parênteses que os seguem chamem a função agrupado expressão:

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

Aplicativos legados, que usam com frequência IIFEs para gerenciar o escopo, especificamente para evitar a poluição do escopo global com variáveis de escopo de função e declarações de função. Antes da introdução do escopo de bloco no ES6, era comum agrupar um script inteiro em um IIFE para evitar a contaminação acidental do escopo global.

Teste seu conhecimento

É possível chamar uma expressão de função nomeada pelo nome fora da ?

Sim
Não