Capítulo 16
Funções e escopo
6 min de leitura 1.038 palavras 2 gravuras
Uma função é um pedaço reutilizável de código, como uma classe CSS que você aplica em vários lugares. O escopo é onde um nome vale. Neste capítulo a Casa da Restinga empacota um cumprimento e aprende o que some quando o bloco acaba.
O exemplo está em exemplos/16-funcoes-escopo/. Natal, fictício. Este volume tem 23 capítulos. Console com F12.
Trabalhe na cópia inicio da etapa. Leia e digite o código; mude uma coisa. Antes de recarregar, anote sua previsão. Depois confira com a referência completa. Se nada mudar, confira o arquivo salvo e o caminho aberto. Blocos adicionais do capítulo podem ser digitados no console; o exemplo completo mostra a aplicação daquela etapa.
O que você vai aprender
- Declarar uma função com
functionereturn. - Passar parâmetros na ordem certa.
- Chamar com parênteses.
- Reconhecer três jeitos de escrever função.
- Entender escopo de função e de bloco (
{ }).
Um bloco com nome
function maisDois(numero) {
return numero + 2;
}
const resposta = maisDois(5);
console.log(resposta);
function maisDois declara. numero é o parâmetro: o apelido do valor que entra. return devolve o resultado para quem chamou.
maisDois(5) chama. O 5 entra no lugar de numero. resposta guarda 7.
Sem return, a função faz o trabalho e devolve undefined.
Mude uma coisa. Chame maisDois(10) em vez de 5. Preveja 12. Recarregue e confira.
Erro comum: escrever maisDois sem (). Sem parênteses, você não chama: só aponta para a função.
Vários parâmetros, uma ordem
function cumprimentar(primeiro, ultimo, titulo, saudacao) {
return `${saudacao} ${titulo} ${ultimo}! Que bom te ver, ${primeiro}.`;
}
console.log(cumprimentar("Iara", "Costa", "chef", "Olá"));
console.log(cumprimentar("Tomás", "Vale", "barista", "Bem-vindo"));
A ordem da chamada é a ordem da lista. Trocar Iara e Costa de lugar muda o sentido da frase.
Quantos parâmetros você quiser. Zero também vale: function abrirPorta() { ... }.
Os textos são fictícios. Não coloque o nome real da turma neste arquivo.
Mude uma coisa. Inverta "Iara" e "Costa" na primeira chamada. Preveja “Olá chef Iara”. Recarregue e confira. Depois restaure.
Erro comum: achar que o nome do parâmetro tem de ser igual ao nome de fora. primeiro recebe o valor, não o nome da variável de fora.
A chamada usa nomes de fora
const cidade = "Natal";
const bairro = "Ponta Negra";
const pais = "Brasil";
function contarOrigem(cidadeCasa, estadoCasa, paisCasa) {
console.log(`Você fala da ${cidadeCasa}, ${estadoCasa}, ${paisCasa}.`);
}
contarOrigem(cidade, bairro, pais);
Quem chama passa os valores. Quem recebe usa os apelidos internos. cidade lá fora e cidadeCasa lá dentro são nomes diferentes para o mesmo texto nesta chamada.
Parênteses depois de um nome = chamada de função. Isso vira um reflexo de leitura.
Mude uma coisa. Passe "Rocas" no segundo argumento. Preveja Ponta Negra sair da frase. Recarregue e confira.
Erro comum: contarOrigem com um argumento só. Os outros parâmetros ficam undefined e a frase esburaca.

Três jeitos, o mesmo ofício
function latir() {
console.log("au");
}
const miar = function () {
console.log("miau");
};
const piar = () => {
console.log("piu piu");
};
latir();
miar();
piar();
A primeira é a declaração clássica. A segunda guarda uma função num const. A terceira é a seta => (um = colado num >).
Há diferenças finas. Neste volume, trate as três como “isso é função”. Prefira function nome() enquanto estiver aprendendo: o nome aparece no erro do console.
Mude uma coisa. Acrescente latir(); de novo no fim. Preveja dois au. Recarregue e confira.
Erro comum: const piar = > { com espaço quebrando a seta. É =>, junto.
Escopo da função
Cada chamada tem um espaço de trabalho. O que você declara dentro não existe fora depois que a função termina.
function maisCinco(numero) {
const segredo = "só aqui dentro";
return numero + 5;
}
maisCinco(10);
console.log(segredo);
A última linha falha: segredo is not defined. O nome viveu entre as { } da função e foi descartado.
return é o jeito honesto de entregar um valor para fora. Sem return (e sem guardar o retorno), o trabalho some.
Mude uma coisa. Troque console.log(segredo) por console.log(maisCinco(10)). Preveja 15. Recarregue e confira.
Erro comum: declarar const total dentro da função e tentar usar total no HTML da página. O HTML não vê o nome. Só o valor devolvido, se você o escrever depois no DOM (capítulo futura).
Escopo do bloco
if, for e while também abrem { }. let e const declarados ali morrem no fim do bloco.
let mesa = 0;
for (let i = 0; i <= 10; i++) {
mesa++;
}
console.log(mesa);
console.log(i);
mesa foi declarada fora: sobrevive. i foi declarada no for: a última linha falha.
Um jeito imperfeito, mas útil agora: um nome vive da { mais próxima até a } que a fecha. Importa onde o nome é declarado, não onde ele é alterado.
Mude uma coisa. Declare let i = 0 antes do for e use for (; i <= 10; i++). Preveja console.log(i) funcionar. Recarregue. (Não é o estilo preferido; só para ver o escopo.)
Erro comum: achar que “já imprimiu i dentro do laço, então existe fora”. Imprimir não exporta o nome.
Fora vive; dentro some
const A = "A";
let F;
function fazer(B) {
const C = "C";
let H = "H";
if (1 + 1 === 2) {
const D = "D";
H = "outra coisa";
}
console.log(H);
F = "F";
}
fazer("B");
console.log(A);
console.log(F);
A é de fora: fazer pode ler. F foi declarado fora e preenchido dentro: sobrevive. B e C morrem no fim da chamada. D morre no fim do if. H foi declarado na função, fora do if: a troca para "outra coisa" vale até a função acabar.
Leia o exemplo completo em exemplos/16-funcoes-escopo/ e marque, no papel, o que imprime e o que quebra. Depois confira as respostas.
Arquivo no disco: o .js. Console no navegador: o que ainda está vivo. 127.0.0.1 se estiver servindo. Publicação não é pedida.
Mude uma coisa. Acrescente console.log(C) depois de fazer("B"). Preveja erro. Recarregue e confira.
Erro comum: console.log no meio da função “para sempre”. Quando a função acaba, aqueles nomes internos não ficam gravados na página.

Atividades
- O que os parênteses fazem em
maisDois(5)quemaisDoissozinho não faz? - Por que a ordem dos argumentos em
cumprimentarimporta? - Por que
console.log(segredo)falha depois demaisCinco(10)? ide umfor (let i = 0; ...)existe depois do laço?
Respostas comentadas
- Chamam a função e passam o
5. Sem(), o nome só aponta para a função. - Porque cada posição preenche um parâmetro. O primeiro texto vai para
primeiro, o segundo paraultimo. segredofoi declarado dentro da função. Ao terminar, o nome é descartado. Oreturnentrega só o número.- Não.
let ivive no bloco dofor. Depois,i is not defined.AeFno exemplo global imprimem;CeDnão.
Referências
O arquivo completo
Referência do exemplo 16-funcoes-escopo, reproduzida aqui para que você possa conferir sem sair da página.
experiments.js
function maisDois(numero) {
return numero + 2;
}
console.log(maisDois(5));
function maisCinco(numero) {
const segredo = "só aqui dentro";
return numero + 5;
}
console.log(maisCinco(10));
assets/stylesheets/main.css
*,
*::before,
*::after { box-sizing: border-box; }
html, body, h1, h2, h3, p, ul { margin: 0; padding: 0; }
img { max-width: 100%; height: auto; }
body {
font-family: "Segoe UI", Tahoma, sans-serif;
line-height: 1.5;
color: #1a2a2c;
background: #f7f3ea;
}
a { color: #0d5c63; }
a:focus-visible, button:focus-visible, input:focus-visible {
outline: 3px solid #c45c26;
outline-offset: 3px;
}
.skip { position: absolute; left: -999px; }
.skip:focus { left: 0.5rem; top: 0.5rem; background: #fff; padding: 0.4rem 0.7rem; z-index: 2; }
.wrap { width: min(44rem, calc(100% - 2rem)); margin-inline: auto; }
header { background: #0d5c63; color: #fff; padding: 1rem 0; }
header a { color: #fff; }
.brand { font-weight: 700; text-decoration: none; }
nav ul { list-style: none; display: flex; gap: 1rem; margin-top: 0.5rem; }
nav a[aria-current="page"] { text-decoration: underline; text-underline-offset: 0.2em; }
main { padding: 1.5rem 0 3rem; }
footer { border-top: 1px solid #ddd4c4; padding: 1rem 0; font-size: 0.95rem; }
article { margin: 1.25rem 0; padding-bottom: 1rem; border-bottom: 1px solid #ddd4c4; }