Fácil JavaScript

Contador com closure

Enunciado

Crie uma função criarContador que retorna uma função. Cada chamada da função retornada incrementa e retorna um contador interno. O contador deve começar em 0 e ser privado (não acessível de fora).

Requisitos

  • A função criarContador não recebe parâmetros.
  • A função retornada incrementa e retorna o valor atual do contador.
  • Duas instâncias de criarContador devem ter contadores independentes.

Código inicial

function criarContador() {
  // seu código aqui
}

const c1 = criarContador();
const c2 = criarContador();
console.log(c1()); // 1
console.log(c1()); // 2
console.log(c2()); // 1

Saída esperada

1
2
1
Ver dica

Use uma variável local dentro de criarContador e retorne uma função que a modifique.

Mostrar solução
function criarContador() {
  let count = 0; // variável privada no escopo da função externa
  return function() {
    count++;
    return count;
  };
}

const c1 = criarContador();
const c2 = criarContador();
console.log(c1()); // 1
console.log(c1()); // 2
console.log(c2()); // 1

Passo a passo

  1. Declaramos criarContador como uma função que não recebe parâmetros.
  2. Dentro dela, criamos a variável count inicializada com 0. Essa variável é local ao escopo de criarContador.
  3. Retornamos uma função anônima que, quando chamada, incrementa count e retorna o novo valor.
  4. Como a função interna referencia count, ela forma uma closure que mantém count vivo mesmo após criarContador retornar.
  5. Cada chamada a criarContador cria um novo escopo, portanto c1 e c2 têm contadores independentes.

Por que funciona

A closure captura o ambiente léxico onde foi criada, incluindo a variável count. Assim, cada instância de criarContador tem seu próprio count isolado. Isso demonstra encapsulamento e estado privado.

Erros comuns

  • Declarar count fora da função: se count for global, todos os contadores compartilharão o mesmo valor.
    let count = 0;
    function criarContador() {
      return function() { count++; return count; };
    }
    
    Isso faz c1 e c2 compartilharem count.
  • Esquecer de retornar a função interna: se não houver return, a função externa retorna undefined.
  • Usar var em vez de let: não é um erro aqui, mas var tem escopo de função; ainda funcionaria, mas let é mais claro.

Outra forma de resolver

Usar um objeto com método:

function criarContador() {
  let count = 0;
  return {
    incrementar: function() { return ++count; }
  };
}
const c = criarContador();
console.log(c.incrementar()); // 1

Preferível quando se deseja expor múltiplos métodos.

Saída esperada

1
2
1