# Funções

## O que são

A palavra função tem muitos significados na programação e ela varia um pouco dependendo do contexto ou linguagem. Para o JavaScript consideramos como função uma serie de instruções (linhas de código) que podem ser executadas/invocadas uma ou mais vezes e que pode receber dados de entrada (inputs ou argumentos) e pode dar dados de saída (outputs ou valor de retorno).

## Sintaxe Padrão

```javascript
function nomeDaSuaFuncao(parametro) {
    // Seu codigo
    return dadoDeRetorno;
}
```

O exemplo acima é uma **declaração** de função, ou seja somente com esse trecho de código a função não é executada, apenas se torna disponível para ser executada. A associação do identificador `nomeDaSuaFuncao` e da função em si acontece antes da execução, quando declarada desta forma.

Outra forma possível de declarar uma função:

```javascript
// Podemos usar const no lugar do let
let nomeDaSuaFuncao = function(parametro) {
    // Seu codigo
    return dadoDeRetorno;
};
```

Dessa forma a função é atribuída a variável `nomaDaSuaFuncao` em tempo de execução.

Note que as funções em JavaScript são variáveis normais e isso traz muita flexibilidade. Em muitas outras linguagens de programação, as funções são um tipo a parte, já no Javascript elas são valores como qualquer outro, ou seja, podemos reatribuir uma variável que era uma função com qualquer outro valor valido.

```javascript
let nomeDaSuaFuncao = function(parametro) {
    // Seu codigo
    return dadoDeRetorno;
};

nomeDaSuaFuncao = "Agora sou uma string";

console.log(nomeDaSuaFuncao ); // "Agora sou uma string"
```

### Executando uma função

```javascript
function testeOla() {
    console.log("Eu sou um teste!");
}

// Ao ser executada "Eu sou um teste!" será imprimido
testeOla();
```

Para executar uma função (informalmente chamado de: *rodar* uma função) basta escrever seu nome e abrir e fechar parêntesis.

```javascript
function testeOla() {
    console.log("Eu sou um teste!");
}

let numeroTeste = 42;

numeroTeste(); // Uncaught TypeError: numeroTeste is not a function
```

No exemplo acima tentamos rodar uma função usando uma variável que não é uma função, essa operação da erro. Certifique-se de rodar apenas variáveis que funções no seu código.

## Valor de retorno

```javascript
teste1() // tudo certo
teste2() // Uncaught ReferenceError: teste2 is not defined

function teste1(parametro) {
    // Seu codigo
    return dadoDeRetorno;
}

let teste2 = function(parametro) {
    // Seu codigo
    return dadoDeRetorno;
};
```

No trecho acima a função `teste1` roda sem problemas, enquanto a `teste2` da erro. Essa diferença é devida a forma de declarar a função. Para a `teste1` a associação da função e seu identificador é feita antes da execução do código, enquanto para a `teste2` é feito durante a execução do código, ou seja, na linha 2, a variável `teste2` ainda não foi definida e a `teste1` sim

Esse processo é chamado de **hoisting** (caso tenha curiosidade veja mais sobre ele [aqui](https://developer.mozilla.org/pt-BR/docs/Glossario/Hoisting)), \_\*\*\_de maneira simplificada, é quando o Javascript leva algumas de suas variáveis para o topo do código para que você consiga ter acesso a elas mesmo antes da sua declaração

## Parâmetros

```javascript
function ola(nome) {
  console.log('Ola, ' + nome + '!');
}

ola("João");   // Ola João!
```

No trecho acima, `nome` é chamado de parâmetro, que atua como uma variável local que pode ser acessada de dentro da função.

Outro nome para a palavra parâmetro é argumento, os dois termos tem leve diferença, mas na pratica são usado como se fossem exatamente iguais.

Uma função pode ter nenhum, um ou mais parâmetros e seus valores são atribuídos em ordem posicional:

```javascript
function matematica(a, b, c) {
  console.log(a + 2*b + 3*c)
}

matematica(1, 2, 3); // 14
matematica(3, 2, 1); // 10
```

Funções também podem retornar um valor, usando a *keyword* `return`:

```javascript
function ola(nome) {
  return 'Ola, ' + nome + '!';
}

let msg = ola("João");


console.log(msg);   // Ola, João!
```

Você so pode retornar um único valor em uma função com o `return`, e todo código depois dele não é executado. Se quiser retornar mais de um valor você pode usar um *objeto* ou *array* (vamos explicar o que ele são posteriormente, não se preocupe!).

Mesmo quando o `return` não é chamado explicitamente no fim de uma função, ela retorna um valor padrão, que é `undefined`

É como se o Javascript adicionasse um `return undefined;` sempre que você não coloca ele explicitamente

```javascript
// function ola(nome) {
//   console.log('Ola, ' + nome + '!');
//   return undefined;
// }

// A função abaixo e acima são equivalentes
function ola(nome) {
  console.log('Ola, ' + nome + '!');
}

let msg = ola("João"); // Ola, João!


console.log(msg); // undefined
```

## Callbacks

As referencias de funções, independente de como foram declaradas, são variáveis e por isso podem ser passadas como argumento para outras funções.

No trecho abaixo a função `rodarFuncao` recebe 3 argumentos.

Ela tenta executar o primeiro argumento como uma função, já que uma função é uma variável como qualquer outra e se ele não for uma função vai dar erro.

O segundo e terceiro argumento da função `rodarFuncao` vão ser passados como parâmetros para a função que ela executa (o primeiro parâmetro)

```javascript
function soma(a, b) {
  console.log('A soma é: 'a + b)
}

function rodarFuncao(fun, argA, argB) {
  fun(argA, argB)
}

rodarFuncao(soma, 10, 2) // A soma é: 12
```

`callback` é o nome de uma função que é passada como argumento para outra função De forma pratica um `callback` normalmente é usado em duas situações:

1. Quando queremos rodar uma função depois que outra coisa acabar

   ```javascript
   function lerDoDisco(nomeDoArquivo, callback) {
     // Aqui vai o codigo para ler os dados do arquivo
     callback()
   }

   function aviso() {
     console.log('Fim da leitura do disco');
   }

   // Primeiro o codigo da função roda e depois a callback roda
   lerDoDisco('t1.js', aviso); // 'Fim da leitura do disco'
   ```
2. Sempre que algo acontece (um evento)

   * No exemplo abaixo quando o botão é clicado a função `minhaFuncao` roda (eventos serão explicados futuramente)

   ```javascript
   function minhaFuncao() {
     console.log('Voce clicou no botao!');
   }

   botao.addEventListener('click', minhaFuncao);
   ```

Uma função pode receber mais um callback por parâmetro

```javascript
function lerDoDisco(nomeDoArquivo, callbackSuccesso, callbackErro) {
  // Aqui vai o codigo para ler os dados do arquivo
  if (conseguiLer) {
      callbackSuccesso()
  }
  else {
      callbackErro()
  }
}

function aviso() {
  console.log('Fim da leitura do disco');
}

// Primeiro o codigo da função roda e depois a callback roda
lerDoDisco('t1.js', aviso); // 'Fim da leitura do disco'
```

## Resumo

Neste capítulo vimos o básico de funções:

* Como declarar e rodar funções
  * Diferentes formas de declarar
* Valores de retorno
* Passando argumentos para funções
* O que são e como usar callbacks


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://uclsanca.gitbook.io/learn/web-basico/javascript/funcoes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
