Funções

Uma função é um bloco de instruções modular e reutilizável usado para executar um conjunto de tarefas relacionadas, como calcular e retornar um valor com base em argumentos fornecidos à função. Assim como todos os valores não primitivos, as funções são objetos. Eles são objetos únicos porque podem ser chamados para executar códigos, receber dados na forma de argumentos e return um valor.

As funções são consideradas objetos de "primeira classe", o que significa que, apesar do comportamento único, elas podem ser usadas nos mesmos contextos que qualquer outro objeto JavaScript. Por exemplo, uma função pode ser atribuída a uma variável, passada como um argumento para outras funções e retornada por outras funções.

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

Uma função definida como uma propriedade de um objeto geralmente é chamada de "método". Assim como acontece com as variáveis declaradas com var, as declarações de função feitas fora de uma função delimitada são adicionadas ao objeto global como métodos.

Declarações de função

Uma declaração de função (também chamada de "instrução de função" ou "definição de função") cria uma função nomeada que pode ser invocada em outro lugar no escopo dela. As declarações de função consistem na palavra-chave function seguida por um identificador, uma lista de parâmetros separados por vírgulas entre parênteses e uma instrução de bloco chamada "corpo da função". Você frequentemente encontrará declarações de função que não terminam com ponto e vírgula. Como uma declaração de função é uma instrução, pontos e vírgulas podem ser inferidos por ASI.

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

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

Devido às decisões iniciais de design do JavaScript, as declarações de função estão sujeitas ao mesmo comportamento de elevação legada das variáveis declaradas com var. Isso significa que uma declaração de função é elevada ao topo do escopo e pode ser chamada antes da declaração como resultado, independentemente de esse escopo ser ou não regido pelo modo restrito:

"use strict";
{
    myFunction();
    function myFunction() {
        console.log( "This is my function." );
    };
}
> "This is my function."

Fora do modo estrito, as declarações de função usam o comportamento legado de escopo do JavaScript. Isso significa que uma declaração de função tem o escopo definido para a função de delimitação mais próxima:

function myFunction() {
    function myNestedFunction() {
        console.log( "This is my nested function." );
    }
    myNestedFunction();
};

myFunction();
> "This is my nested function."

myNestedFunction();
>Uncaught ReferenceError: myNestedFunction is not defined

No modo estrito, as declarações de função têm o escopo definido para o bloco delimitado mais próximo, como acontece com as variáveis declaradas usando let ou const:

"use strict";
{
    function myFunction() {
        console.log( "This is my function." );
    };
}

myFunction();
> Uncaught ReferenceError: myFunction is not defined

Chamadas de função

Assim como nas variáveis, o identificador usado ao declarar uma função atua como um nome simbólico para um valor. Fazer referência a uma função apenas pelo identificador retorna apenas o objeto de função e não executa a função que ela contém:

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

myFunction;
> myFunction() {
   console.log( "This is my function." );
}

Para executar o código dentro do corpo da função, chame (ou invoque) a função seguindo o nome dela com um par de parênteses correspondente:

function myFunction() {
    console.log( "My function has been executed." );
}

myFunction();
> "My function has been executed."

Os parâmetros na definição da função atuam como variáveis de marcador de posição para valores que podem ser transmitidos para o corpo da função quando ela é chamada. Os valores entre parênteses quando uma função é chamada são "argumentos", embora você possa ver "argumentos" usados para descrever argumentos e parâmetros em algumas documentação:

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

Se um argumento esperado for omitido, o parâmetro resultante conterá um valor undefined, porque o parâmetro é declarado para o corpo da função, mas não é inicializado com um valor:

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction();
> "The value is: undefined."

Para definir valores de parâmetro padrão, inicialize-os da mesma forma que você inicializa uma variável: um operador de atribuição (=) seguido por um valor. Se você especificar posteriormente um argumento para essa função, esse novo valor modificará o padrão:

function myFunction( myParameter = "omitted" ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

myFunction();
> "The value is: omitted."

O corpo de uma função sem seta também tem acesso a um objeto arguments com índice zero, matriz, que contém valores passados como argumentos, mesmo que a definição da função não especifique parâmetros:

function myFunction() {
   console.log( arguments );
};

myFunction( 3, true, "My string" );
> Arguments { 0: 3, 1: true, 2: "My string", … }

Funções variadas

O objeto arguments permite criar funções variáveis básicas, que podem aceitar um número variável de argumentos:

function myFunction() {
    let result = "";
    for (let i = 0; i < arguments.length; i++) {
        result += arguments[i] + " - ";
    }
    console.log( result );
};

myFunction( "My first string", "My second string", "my third string" );\
> "My first string - My second string - my third string - "

No entanto, essa abordagem para funções variadas raramente é usada no desenvolvimento moderno de JavaScript. É mais comum usar a sintaxe de parâmetro REST, que é mais moderna e legível, porque cria um parâmetro nomeado inicializado como uma matriz que contém argumentos além daqueles explicitamente especificados:

function myFunction( mySeparator, ...myStrings ) {
  console.log( myStrings.join( mySeparator ) );
};

myFunction( " - ", "My first string", "My second string", "my third string" );
> "My first string - My second string - my third string"

Ao contrário da vinculação parameter, a sintaxe do parâmetro REST funciona conforme esperado com os parâmetros da função arrow:

function myOuterFunction() {
    let myInnerArrowFunction = ( ...myParams ) => {
        console.log( myParams[ 0 ] );
    }
    myInnerArrowFunction( true );
};

myOuterFunction( false );
> true

let myArrowFunction = ( ...myParams ) => {
    console.log( myParams[ 0 ] );
};

myArrowFunction( true );
> true`
``