Dia 7 — Funções

Informatica · Conteudo · publicado em 05/10/2026
Aula 1

Declarar e chamar uma função

Declarar e chamar uma função

A pergunta "como declarar função" tem uma resposta: function mais o nome, e a

função só executa quando alguém

chamar por esse nome. Ela existe para nomear uma tarefa, receber dados,

processar e devolver resultado.

function somar(a, b) {
  return a + b;
}

console.log(somar(2, 3));   // 5

O que está entre parênteses na declaração são os parâmetros; o que está entre

parênteses na chamada são os argumentos. No corpo, os parâmetros são nomes

que valem o que foi passado. O return é o retorno: ele encerra a função e

entrega o valor.

Sem return, a função devolve undefined. Esse detalhe importa quando o

resultado é usado em conta:

function semRetorno() { }
console.log(semRetorno() + 1);   // NaN

O return também encerra a função na hora. O que está depois dele não roda, e é

por isso que o retorno antecipado funciona como saída única.

As duas linhas do exemplo que tratam disso são `sem return: undefined |

undefined + 1 = NaN e retorno antecipado: vazio | tem itens`. A primeira

confirma a regra do undefined com a conta ao lado: sem return, o valor é

undefined, e undefined + 1 é NaN. A segunda mostra que classifica(0) saiu

pela linha do if e classifica(3) pela última — e o return 'tem itens' só é

alcançado quando o if não pegou.

A função seta, que é a forma do React

A função seta ou arrow function é a forma curta, com => no lugar de

function:

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

Quando o corpo é uma única expressão, as chaves e o return podem ficar de fora.

Quando o corpo tem mais de um comando, as chaves voltam e o return precisa ser

escrito:

const descrever = (total) => {
  const plural = total === 1 ? '' : 's';
  return `${total} tarefa${plural}`;
};

Em React Native, quase todo código é arrow function: componente é função,

callback de botão é função, função passada para map é função. A **função

anônima** é a que não tem nome — é o que a seta produz quando você não escreve

const nome =.

O exemplo mostra os dois corpos da seta lado a lado. dobrar tem uma expressão

só e sai em seta curta: 42, sem chaves e sem return — o próprio corpo é o

valor devolvido. descrever tem dois comandos e a linha sai

seta com bloco: 1 tarefa | 5 tarefas: o plural foi calculado numa linha e

devolvido noutra, o que obrigou as chaves e o return explícito. São as duas

formas do parágrafo, com o resultado de cada uma.

A função anônima aparece na linha do forEach, que imprime `anonima:

estudar e anonima: treinar. Ali não existe const nome =`: a seta foi passada

direto como argumento. É por isso que o nome do exemplo importa — o forEach

chama a mesma função duas vezes, uma por item, e cada chamada é anônima e igual.

A IIFE: chamar na hora da declaração

Imediatamente executada é o nome do padrão em que a função é declarada e

chamada na mesma linha, entre parênteses:

(function () {
  console.log('roda uma vez, ao carregar o arquivo');
})();

O uso no app é inicializar configuração, registrar log e montar estado inicial —

tudo o que precisa acontecer uma vez, quando o módulo carrega.

O exemplo mostra a IIFE escrevendo IIFE: rodou uma vez, e o nome da linha já é

o resumo: uma vez, no carregamento. O (() => { ... })() é a mesma coisa

escrita com seta, e é a forma que aparece nos arquivos de configuração.

O detalhe é o segundo parêntese. Os parênteses externos primeiro agrupam a

função — sem eles, function () {} na linha seguinte seria lido como declaração

e não como valor — e o segundo parêntese é a chamada. (function () {}) sem

o () final define a função e não a executa.

Hoisting: a função inteira sobe

A declaração de função é içada (hoisting): o JavaScript sobe a declaração

inteira para o topo do arquivo antes de executar qualquer linha. Chamar uma função

antes da linha em que ela foi escrita funciona:

console.log(dizerOi());   // funciona

function dizerOi() {
  return 'oi';
}

let e const não sobem. Usá-los antes da declaração é erro:

ReferenceError: Cannot access 'x' before initialization. E var sobe, mas

sobe sem valor — ler antes da atribuição devolve undefined, não o valor.

A regra prática: função declarada com function pode ser chamada em qualquer

ponto do arquivo; arrow function precisa estar declarada antes de ser usada.

O exemplo põe os três comportamentos em linhas seguidas, e é a ordem das linhas

que prova a regra. hoisting de function: oi sai antes da linha que declara

dizerOi. Depois vem `let nao sobe: ReferenceError - Cannot access

'antesDaDeclaracao' before initialization, e o erro precisa de try/catch`

porque derrubaria o arquivo inteiro — é a diferença entre um erro de sintaxe,

que nem chega a executar, e um de execução, que para na linha.

A terceira linha é o caso intermediário: var sobe sem valor: undefined. O var

sobe, como o function, mas sobe vazio: a linha var valorVar = 10 continua

abaixo do return, então a função devolveu undefined e não 10. As três

linhas juntas são a resposta completa: function sobe inteiro, var sobe vazio,

let e const não sobem.

E o detalhe de .name está na penúltima linha: `nome: somar | nome da seta:

dobrar. Uma seta declarada com const dobrar = ... tem o nome do const`, mesmo

escrita como valor anônimo — é assim que o map imprime o nome de cada função

quando algo dá erro dentro dela.

A última linha do exemplo é a que abre a aula seguinte:

funcao que recebe funcao: [ 'ESTUDAR', 'TREINAR' ]. aplicar recebe a lista e

a função, e entrega o map dela. Passar função como argumento é o que permite o

map, o filter e o useState — e o detalhe é que a função passada foi uma

seta anônima que só existia naquele argumento.

Exemplo

// Declarar e chamar funcao: a forma com `function` e a funcao seta, que e
// a forma que o React Native usa em quase todo lugar.
function somar(a, b) {
  return a + b;
}
console.log('funcao declarada:', somar(2, 3));

// parametro e o nome na declaracao; argumento e o que foi passado
function saudar(nome) { return `ola, ${nome}`; }
console.log('saudar:', saudar('Ana'));

// sem return, a funcao devolve undefined
function semRetorno() { }
console.log('sem return:', semRetorno(), '| undefined + 1 =', semRetorno() + 1);

// o return encerra a funcao: o que esta depois nao roda
function Classifica(total) {
  if (total === 0) return 'vazio';
  return 'tem itens';                 // o return anterior ja saiu
}
console.log('retorno antecipado:', Classifica(0), '|', Classifica(3));

/* funcao seta: corpo de uma expressao nao precisa de chaves nem return */
const dobrar = (n) => n * 2;
console.log('seta curta:', dobrar(21));

// com mais de um comando, as chases voltam e o return e escrito
const descrever = (total) => {
  const plural = total === 1 ? '' : 's';
  return `${total} tarefa${plural}`;
};
console.log('seta com bloco:', descrever(1), '|', descrever(5));

// funcao anonima: o que a seta produz quando nao ha const nome =
const tarefa = ['estudar', 'treinar'];
tarefa.forEach((item) => console.log('anonima:', item));

/* IIFE: chamada imediata, roda uma vez ao carregar o arquivo */
(function () {
  console.log('IIFE: rodou uma vez');
})();

/* hoisting: function sobe inteiro antes de executar */
console.log('hoisting de function:', dizerOi());
function dizerOi() { return 'oi'; }

/* let nao sobe: usar antes da declaracao e ReferenceError */
try {
  console.log(antesDaDeclaracao);
  let antesDaDeclaracao = 1;
} catch (erro) {
  console.error(erro.constructor.name + ': ' + erro.message);
  console.log('let nao sobe:', erro.constructor.name, '-', erro.message);
}

/* var sobe sem valor */
console.log('var sobe sem valor:', (function () { return valorVar; var valorVar = 10; })());

/* nome da funcao, util no log */
console.log('nome:', somar.name, '| nome da seta:', dobrar.name);

/* funcao que recebe funcao: o padrao do map */
function aplicar(valores, transformar) {
  return valores.map(transformar);
}
console.log('funcao que recebe funcao:', aplicar(tarefa, (t) => t.toUpperCase()));

Saída real

funcao declarada: 5
saudar: ola, Ana
sem return: undefined | undefined + 1 = NaN
retorno antecipado: vazio | tem itens
seta curta: 42
seta com bloco: 1 tarefa | 5 tarefas
anonima: estudar
anonima: treinar
IIFE: rodou uma vez
hoisting de function: oi
let nao sobe: ReferenceError - Cannot access 'antesDaDeclaracao' before initialization
var sobe sem valor: undefined
nome: somar | nome da seta: dobrar
funcao que recebe funcao: [ 'ESTUDAR', 'TREINAR' ]
Aula 2

Argumentos, escopo e funções anônimas

Argumentos, escopo e funções anônimas

O que acontece com o valor que entra na função depende do tipo dele. **Argumento

por valor** significa que a função recebe uma cópia: mudar o parâmetro não muda o

argumento. Os parâmetros são os nomes na declaração; os argumentos são os valores

na chamada. Argumento por referência significa que a função recebe o objeto

mesmo: mudar a propriedade muda o objeto de quem chamou.

function renomear(usuario, nome) {
  usuario.nome = nome;   // mudou o objeto de quem chamou
}
const ana = { nome: 'Ana' };
renomear(ana, 'Bia');
console.log(ana.nome);   // 'Bia'

Número, texto, booleano, null e undefined são copiados. Objeto e array são

passados como referência — é por isso que push dentro de uma função altera o

array de fora, e é por isso que uma função que precisa alterar sem mexer no

original precisa devolver um array novo.

O exemplo separa os dois lados em duas linhas. por valor: 101 vem da função que

recebe 1 e 3, escreve 99 em a e devolve 99 + 3: o a original da

chamada ficou valendo 1, e ninguém consegue ver isso pelo resultado. `por

referencia: Bia | mesmo objeto: true vem da função que escreve no usuario` e

devolve o próprio usuario; o ana.nome saiu 'Bia' e a comparação

ana === resultado saiu true, que é a prova de que não existiu cópia.

O true dessa segunda linha é o detalhe que fecha a regra. Uma cópia daria

false — e o que o console.log mostra é que a escrita dentro da função

alcançou o objeto de quem chamou.

Parâmetro padrão e rest

Parâmetro padrão é o valor usado quando o argumento não vem:

function saudar(nome, prefixo = 'ola') {
  return `${prefixo}, ${nome}`;
}

Rest (...) junta o que sobra dos argumentos num array:

function contar(...numeros) {
  return numeros.length;
}
contar(1, 2, 3);   // 3

O ... no lugar do nome é o spread, e o mesmo operador em outro lugar faz o

oposto: espalha o conteúdo. A diferença é a posição.

O exemplo chama contar(1, 2, 3) duas vezes na mesma linha e o console responde

rest: 3 | o array: 3. Os dois 3 são o mesmo número: o length e o próprio

array com os três itens — o rest sempre chega como array, mesmo com um

argumento só, porque é uma lista de argumentos que sobraram.

A assinatura é o que define o rest: ele precisa ser o último parâmetro,

porque tudo depois dele seria argumento sem nome. Com (primeiro, ...resto), o

primeiro sai do array e resto fica com o que sobrou — e é assim que se pega

o primeiro item de uma lista de argumentos sem shift.

Escopo: o nome de dentro não existe fora

A variável local é a que fica dentro da função. Função cria escopo próprio. Nome declarado dentro só existe dentro:

const global = 'visivel';
function f() {
  const local = 'so aqui dentro';
}

Ler local fora da função é ReferenceError, e o mesmo acontece com const e

let. A variável global é o nome declarado no topo do arquivo, fora de

qualquer função — ela é alcançável de todo lugar, e é por isso que o código do

app evita declarar tudo global: com nome global, dois componentes que usam

total estão usando o mesmo total.

O exemplo mostra os dois lados em duas linhas. `escopo: visivel em todo o

arquivo / so dentro da funcao` vem da função que usa os dois nomes: o global foi

lido de dentro, e o local foi lido no mesmo return. A linha seguinte tenta ler

o local de fora e o console responde `local existe fora? ReferenceError:

local is not defined`.

O ReferenceError é a resposta que fecha o parágrafo: não é undefined, é erro.

E o nome global visível de dentro não é o mesmo objeto que o local — são dois

nomes independentes, e a função só enxerga os dois porque foi escrita no mesmo

arquivo.

Closure: a função guarda o escopo

Closure é a função junto com o acesso às variáveis do escopo onde foi criada.

A função interna continua enxergando n depois que a externa terminou:

function criarContador() {
  let n = 0;
  return () => { n = n + 1; return n; };
}

Cada chamada de criarContador cria um n novo e uma closure nova. É o que faz

o contador guardar o valor entre chamadas, e é o mesmo mecanismo que sustenta o

estado de um componente.

A linha do exemplo é closure: 1 2 | nova instancia: 1, e ela traz as duas

provas numa frase. As duas primeiras chamadas do mesmo contador devolvem 1 e

2 — o n sobreviveu entre elas, apesar de criarContador já ter terminado. A

terceira é uma chamada nova de criarContador(), e devolve 1 outra vez.

Esse 1 repetido é o ponto: se o n fosse global, a terceira chamada

continuaria em 2. Cada chamada cria uma caixa nova, e é a caixa que a

closure carrega junto. É exatamente esse mecanismo que o useState usa, com a

diferença de que o estado é guardado pelo runtime e não por um let do

arquivo.

Função anônima e os atalhos

A função anônima é a seta sem nome, e é a forma de quase todo callback:

aoTerminar(tarefas, (total) => console.log(total));

Os curto circuits — curto circuito é o nome técnico — dos && e || dentro de função substituem o if de uma

linha. && devolve a esquerda quando ela é falsy — é o atalho que evita acessar

propriedade de quem não existe. || devolve a esquerda quando ela é truthy, e é

a forma curta do valor padrão quando o valor existe:

function nomeSeguro(usuario) {
  return (usuario && usuario.nome) || 'sem nome';
}

O detalhe do this vale registro: a função seta não tem this próprio. Ela

não sabe de qual objeto foi chamada, e por isso não funciona como método de

objeto. Quando o método precisa de this, é function que se usa.

O exemplo chama a função anônima como argumento e o console responde `funcao

anonima chamada: 2 — o 2 é o length da lista que aoTerminar` recebeu, e

não uma variável de fora. É a função anônima fazendo o serviço completo, com o

dado entregue pelo dono da função.

Os atalhos aparecem na linha seguinte, com os dois lados de uma vez:

&& e ||: Ana | sem nome. Com { nome: 'Ana' }, o && devolveu o nome e o ||

aceitou; com null, o && cortou antes do .nome e o || forneceu 'sem nome'.

E a linha do this é seta nao tem this proprio: sem this. A seta está como

propriedade do objeto relogio, tem horas: 10 ao lado, e mesmo assim não

consultou nada disso — devolveu o texto fixo. Uma function no mesmo lugar

receberia this valendo relogio e leria this.horas.

A última linha é o padrão do onPress: aoClicar('marcar como feita')() sai

executou: marcar como feita. A função devolve outra função, e essa segunda

chamada executa a ação com o dado que a primeira recebeu. É assim que o botão do

app guarda a ação sem executar nada no momento de renderizar.

Exemplo

// Argumentos, escopo e funcoes anonimas: o que acontece com o valor que
// entra e o que fica depois da chamada.

/* argumento por valor: o numero que entra e uma copia */
function somar(a, b) { a = 99; return a + b; }
console.log('por valor:', somar(1, 2));

/* argumento por referencia: o objeto que entra e o mesmo objeto */
function renomear(usuario, nome) { usuario.nome = nome; return usuario; }
const ana = { nome: 'Ana' };
const resultado = renomear(ana, 'Bia');
console.log('por referencia:', ana.nome, '| mesmo objeto:', ana === resultado);

/* parametro padrao: quando o argumento nao vem, o padrao entra */
function saudar(nome, prefixo = 'ola') { return `${prefixo}, ${nome}`; }
console.log('padrao usado:', saudar('Ana'), '| padrao trocado:', saudar('Ana', 'bom dia'));

/* rest: o que sobra dos argumentos vira array */
function contar(...numeros) { return numeros.length; }
console.log('rest:', contar(1, 2, 3), '| o array:', contar(1, 2, 3));

/* escopo: o nome de dentro nao existe fora */
const global = 'visivel em todo o arquivo';
function usarEscopo() {
  const local = 'so dentro da funcao';
  return `${global} / ${local}`;
}
console.log('escopo:', usarEscopo());
console.log('local existe fora?', (() => { try { return local; } catch (e) { return e.constructor.name + ': ' + e.message; } })());

/* closure: a funcao guarda acesso ao escopo onde foi criada */
function criarContador() {
  let n = 0;
  return () => { n = n + 1; return n; };
}
const contador = criarContador();
console.log('closure:', contador(), contador(), '| nova instancia:', criarContador()());

/* funcao anonima recebida como parametro */
function aoTerminar(tarefas, quando) {
  quando(tarefas.length);
}
aoTerminar(['estudar', 'treinar'], (total) => console.log('funcao anonima chamada:', total));

/* atalhos && e || dentro da funcao */
function nomeSeguro(usuario) {
  return usuario && usuario.nome || 'sem nome';
}
console.log('&& e ||:', nomeSeguro({ nome: 'Ana' }), '|', nomeSeguro(null));

/* o this dentro da funcao seta */
const relogio = { horas: 10, descrever: () => 'sem this' };
console.log('seta nao tem this proprio:', relogio.descrever());

/* funcao que devolve funcao, o padrao do onPress */
function aoClicar(acao) {
  return () => console.log('executou:', acao);
}
aoClicar('marcar como feita')();

Saída real

por valor: 101
por referencia: Bia | mesmo objeto: true
padrao usado: ola, Ana | padrao trocado: bom dia, Ana
rest: 3 | o array: 3
escopo: visivel em todo o arquivo / so dentro da funcao
local existe fora? ReferenceError: local is not defined
closure: 1 2 | nova instancia: 1
funcao anonima chamada: 2
&& e ||: Ana | sem nome
seta nao tem this proprio: sem this
executou: marcar como feita