Funções

Funções em Javascript

De modo geral, o javascript conta com uma estrutura de blocos popularmente conhecida como funções.

Elas são consideradas "subprogramas" de um programa principal, por vezes chamadas de código externo/interno de uma aplicação JS.

As funções seguem um esquema bem parecido com as estruturas condicionais (if/else) e também com as estruturas de iterações (for, while...), isso porque ela também trabalha com blocos de código.

A sintaxe de uma função é a seguinte:

function nome() {
//Códigos que serão executados pela função
}

Para declararmos uma função primeiro temos que nos certificar de algumas coisas:

1) Cada função possui nome específico, sabendo disso, o nome da sua função deve exemplificar do que ela se trata.

let valor = 2;

function somaMaisDois(){
valor = valor + 2;
}

function adicionaMicilini(){
valor = valor + ", micilini";
}

function verificaOToken(){
if(soma == 'AS34FS'){
console.log('Tudo certo!');
}else{
console.log('Token ERRADO!');
}
}

Observe que só de ler o nome da função, nós já conseguimos entender o que ela faz.

2) Quando você estiver escrevendo o nome de uma função, a primeira letra deve sempre começar em minúsculo, e cada termo a seguir deve iniciar com letra maiúscula.

function verificaToken(){
}

function atualizaSenha(){
}

function retornaDadosDoUsuario(){
}

3) Cada função deve fazer uma única coisa por vez. Caso isso não seja possível, tente especificar seu objetivo no nome da função.

function verificaDatas(){//Função que verifica as datas
}

function verificaDatasEInsereAtualizaValor(){//Evite isso, pois essa função pode virar duas
}

Essas dicas foram retiradas do livro Código Limpo, leitura essencial para qualquer desenvolvedor que está iniciando a sua jornada.

Diferenças entre Funções e Condicionais/Iterações

A grande diferença entre as funções das estruturas condicionais e iterações, é que no caso das funções, o javascript passa direto por elas, sem executa-las.

Isso quer dizer que se você declarar uma função, e não chama-la, o conteúdo ali existente nunca será executado.

console.log('Início do Programa em JS');

function minhaFuncao(){
console.log('Entrei na função...');
}

console.log('Final do Programa em JS');

Isso é o que difere as funções das estruturas condicionais e iterações, enquanto essas estruturas do javascript elas meio que tentam fazer a execução antes de entrar no bloco, no caso das funções ele nem mesmo tenta fazer a execução delas (ao menos que exista um código que chame esta função).

E é por esse motivo que as funções são consideradas como um "subprograma".

Chamando uma Função

Como vimos anteriormente, declarar uma função, num primeiro momento parece ser algo relativamente fácil, não é mesmo?

Mas não adianta nada declarar uma função, se não conseguimos chama-la, certo?

Pois do que adianta declarar uma função se ela nunca será chamada em outra parte do código, não faz sentido declara-la 😅

Para chamar uma função é simples, basta repetir seu nome em qualquer parte do código:

function minhaFuncao(){
console.log('Função foi chamada!');
}

minhaFuncao();//É assim que se chama uma função

Funções com Parâmetros

Os parâmetros de uma função são chamados de argumentos da função.

Eles são passados por dentro dos parênteses da função, e é como declarar variáveis ali dentro, veja como é simples:

function mostraNome(nome){//Recebendo o argumento e salvando na variável temporária 'nome'
console.log('Seu nome é: ' + nome);//Aqui estamos usando a variável temporária 'nome' com console
}

mostraNome('Micilini');//Não se esqueça de passar o valor quando for chamar a função ;)

Lembrando que devemos passar o valor quando chamarmos essa função.

mostraNome('Micilini');

Funções com Múltiplos Parâmetros

Também é possível passar mais de um único argumento para dentro de uma função, basta apenas que você os separe por vírgulas:

function montaTexto(nome, idade, rank){
console.log('Nome: ' + nome + ', Idade: ' + idade + ', Rank: ' + rank);
}

montaTexto('João Vitor', 23, 'Classe A');

Podemos enviar quantos argumentos quisermos para dentro de uma função.

Só que de acordo com a metodologia de código limpo ensinado no famoso livro Código Limpo, é recomendado que uma função conte apenas com 2 a no máximo 3 argumentos.

O motivo? Recomendo a leitura do livro para saber 🙃

O que será que acontece quando declaramos argumentos para uma determinada função, e na hora de chamar não passar nenhum argumento?

function montaTexto(nome, idade, rank){
console.log('Nome: ' + nome + ', Idade: ' + idade + ', Rank: ' + rank);
}

montaTexto();//Erro no Javascript, pois os 3 argumentos são obrigatórios

Como o JS é uma linguagem bem flexível e dinâmica, a função ainda é executada normalmente, a diferença é que o conteúdo das variáveis temporárias serão salvas como undefined.

Nesse caso quando temos uma função com argumentos e chamamos essa função sem passar os argumentos, o JS atribui o valor de undefined para esses argumentos.

Diferente de algumas outras linguagens de programação onde chamar uma função sem passar os argumentos, ocasionaria um erro de compilação de código.

Argumentos Opcionais

Você sabia que é possível chamar uma função sem a necessidade de passar algum argumento?

Isso é possível por meio dos argumentos opcionais, e para declara-los você precisa definir um valor padrão para aquele argumento, veja como é fácil:

function montaTexto(nome = "fulano"){
console.log('Seu nome é: ' + nome);
}

montaTexto();//Retorna 'Seu nome é: fulano'

montaTexto('Micilini');//Retorna 'Seu nome é: Micilini'

Mais um exemplo onde o segundo argumento é opcional:

function montaTexto(nome, rank = 0){
console.log('Seu nome é: ' + nome + ', Rank: ' + rank);
}

montaTexto('João Vitor');//Retorna 'Seu nome é: João Vitor, Rank: 0'

montaTexto('Micilini', 3);//Retorna 'Seu nome é: Micilini, Rank: 3'

Lembrando que podemos declarar quantos argumentos opcionais quisermos, ok?

O que acontece quando o primeiro e o terceiro argumento é obrigatório, mas o segundo é opcional?

function montaTexto(nome, idade = "nasceu ontem", rank){
console.log('Seu nome é: ' + nome + ', Rank: ' + rank + ', Idade: ' + idade);
}

montaTexto('Micilini', 2);

O JS não tem (ainda) capacidade de entender que o segundo argumento é opcional e com isso atribuir o valor 2 para a variável temporária rank.

Nesse caso, o resultado final seria: "Seu nome é: Micilini, Rank: undefined, Idade: 2".

O que acontece quando declaramos mais argumentos do que a função recebe?

function funcaoUm(nome, idade){
console.log(nome + idade);
}

funcaoUm('Micilini', 25, 12, 'qweqwe', 234);//'Micilini25'

Nesse caso o JS ignora os argumentos adicionais e continua executando normalmente a função.

Funções com Retorno

As funções não servem apenas como "subprogramas" que executam um bloco de código e fica por isso mesmo.

Também é possível chamar uma função e recuperar o valor que é retornado por ela. Para isso usamos o comando return.

let numero = 2;

function retornaSomaTres(numero){
return numero + 3;
}

console.log('O resultado é: ' + somaTres(numero));//5
function retornaAlgo(nome){
let numero = 0;
if(numero == 1){
return 0;
}
return nome;
}

let resultado = retornaAlgo('Micilini');//Micilini

OBS: Nem todas as funções que você criar devem possuir um retorno, pois depende exclusivamente da lógica do seu código.

É importante ressaltar também que quando o return é executado, todo e qualquer código existente abaixo dele, não será executado pelo javascript, pois o comando return faz a função terminar ali:

function retornaNome(nome){
return nome;
console.log('Nunca serei executado...');
}

let resultado = retornaNome('Micilini');//Micilini

Declarando Funções dentro de Variáveis

Uma das possibilidades que o JS nos dá é a capacidade de declarar funções dentro de variáveis, e chamar essas variáveis como se fossem funções.

Esse ato também é conhecido como uma função anônima.

Cuja finalidade é criar uma função como se ela fosse um objeto comum. Vejamos como essas funções se comportam:

let anonima = function(){
console.log('Anônima foi executada');
};

anonima(); //executa a função anônima

Perceba que no caso dessas funções, nós não precisamos declarar o nome da função em si, pois o próprio nome da variável já é considerado o nome da função.

Funções anônimas também podem receber argumentos e retornar valores, vejamos um exemplo:

var somaDois = function(numero){
return numero + 2;
};

console.log('Resultado é: ' + somaDois(8));//10

3 Tipos de declaração de funções

Existem 3 formas diferentes de se declarar funções com o JS, vejamos cada uma delas a seguir.

Function Constructor

Abaixo temos uma função declarada como function constructor, onde conseguimos passar 3 parâmetros para o construtor da função em formato de texto:

var multiplicar = new Function('x', 'y', 'return x * y;');

console.log(multiplicar(2,2));//4

O comando acima está recebendo duas variáveis, que são x e y respectivamente, e executando um simples comando que retorna a multiplicação dessas duas variáveis.

Você sabia que é possível escrever mais de uma única linha de código dentro do function constructor?

var exemplo = new Function("alert('Olá mundooo'); alert('Olá Micilini'); console.log('resultado é X')");
exemplo();

Function Declaration

Como visto anteriormente a function declaration, é a forma de se declarar uma função atribuída a uma variável de forma anônima:

var multiplicar = function(x, y) {
return x * y;
};

console.log(multiplicar(2,2));//4

Function Expression

Por fim nós temos a function expression, que é a forma de declarar uma função normalmente definindo atributos para ela:

var multiplicar = function nomeFuncao(x, y) {
return x * y;
};

console.log(multiplicar(2,2));//4

function nomeFuncao(x, y) {
return x * y;
};

console.log(nomeFuncao(2,2));//4

Funções dentro de Funções

No JS é possível declarar funções dentro de funções, como ocorre no exemplo abaixo:

function funcaoUm(){
console.log('Função 1 chamada');
funcaoUmDois();
function funcaoUmDois(){
console.log('Função 2 chamada');
}
}

funcaoUm();

Perceba que chamamos a funcaoUmDois() dentro da funcaoUm(). Agora se tentarmos chamar a funcaoUmDois() fora da funcaoUm(), como acontece no exemplo abaixo:

function funcaoUm(){
console.log('Função 1 chamada');
funcaoUmDois();
function funcaoUmDois(){
console.log('Função 2 chamada');
}
}

funcaoUm();
funcaoUmDois();//Erro 'funcaoUmDois()' não está definida

O JS não encontrará a função especificada por um problema de escopo de código!

Lembra que em aulas passadas foi dito que tudo que é declarado dentro de um bloco só existe naquele bloco? Então... a funcaoUmDois() só existe dentro da funcaoUm(), o que significa que ela só pode ser chamada lá dentro daquele escopo.

Existe também a possibilidade de declararmos mais de uma função no escopo principal do projeto de modo a fazer com que elas se comuniquem, veja:

function um(){
console.log('UM');
}

function dois(){
um();//Chama a função 'um'
console.log('DOIS');
}

dois();

Funções do tipo Arrow

Com as novas versões do Javascript (ECMAScript 6) diversas implementações e funcionalidades interessantes foram sendo adicionadas a linguagem, e uma delas é uma sintaxe resumida de se escrever funções.

As funções do tipo arrow, são consideradas uma forma mais simplificada de escrever funções onde o retorno é automática, ou seja, não precisamos escrever o comando return.

A sintaxe é a seguinte:

() => {}

Vejamos abaixo um exemplo de uma função normal em comparação com uma função do tipo arrow:

//Função anônima escrita normalmente
const digaOla = function(nome) {
return `Olá ${nome}!`;
}

//Função do tipo Arrow
const digaOlaMundo = nome => `Olá ${nome}, Mundo!`;

Vemos que conseguimos escrever uma função que inicialmente ocupava 3 linhas em somente uma única linha, que maneiro não?

Veja mais exemplos da utilização das funções do tipo arrow:

const adicao = (a, b) => a + b;

const subtracao = (a, b) => a - b;

É importante ressaltar que até agora nós vimos funções do tipo arrow que possuem apenas 1 linha de código, em casos como esses o retorno será feito de forma automática.

Agora quando temos uma função do tipo arrow que contém mais de uma linha de código... precisamos usar as chaves e o comando return.

const verificaNome = nome => {
if(nome == 'micilini'){ return true; }
return false;
}

Operador Yield

No Javascript, temos um operador capaz de pausar e resumir uma função de gerador, conhecido como Yield.

Para isso a função precisa levar o asterisco no final do seu nome (function*):

function* mostraMensagens() {
console.log('Olá...');
yield 1;
console.log('Mundo...');
yield 2;
console.log('!!!');
yield 3;
}

let funcao = mostraMensagens();

console.log(funcao.next());//Olá... {done: false, value: 1}
console.log(funcao.next());//Mundo... {done: false, value: 2}
console.log(funcao.next());//!!! {done: false, value: 3}

Observe que estamos usando o comando next() para seguir para as próximas etapas da função.

Podemos ver acima que o Yield está relacionado com os números 1, 2 e 3. Aqueles números representam o valor de retorno retornado a cada vez que usamos o next().

Mas podemos passar qualquer valor ali, desde uma string, outro número, valor booleano ou quem sabe um array, objetos e afins.

function* mostraMensagens() {
console.log('Olá...');
yield [33, 70, 81];
console.log('Mundo...');
yield true;
console.log('!!!');
yield 'chegou...';
}

let funcao = mostraMensagens();

console.log(funcao.next());//Olá... {done: false, value: [34, 70, 81]}
console.log(funcao.next());//Olá... {done: false, value: true}
console.log(funcao.next());//Olá... {done: false, value: 'chegou...'}
console.log(funcao.next());//{done: true, value: undefined}

Como o retorno do next() é sempre um objeto, podemos comparar a chave 'done' para saber se chegamos até o final (isso se o resultado for true). Da mesma forma como podemos usar a lógica do Yield dentro de um loop.

let contador = 0;
let finalizado = true;

function* adicionarUm(){
contador++;
yield 'Parada Um...';
contador++;
yield 'Parada Dois..';
}

let funcao = adicionarUm();

do{
let resultado = funcao.next();
if(resultado.done == true){
break;
}
console.log('Não chegou ao fim...');
}while (finalizado)

console.log('Já posso desligar o programa... FINALIZADO');

//Resultado:

/*
"Não chegou ao fim..."
"Não chegou ao fim..."
"Já posso desligar o programa... FINALIZADO"
*/

Conclusão

Neste conteúdo você aprendeu como funciona o universo das funções no Javascript, e como eles podem ser úteis no seu dia a dia como desenvolvedor.

Te aguardo na próxima fase 😎