Chegamos ao fim do primeiro módulo. Em nove artigos você percorreu um caminho sólido — da sintaxe básica até conceitos que muitos desenvolvedores levam meses para entender de verdade.
Este artigo tem dois objetivos: primeiro, revisar os conceitos centrais do módulo com exemplos rápidos. Segundo, construir um projeto real que une tudo em um único programa funcional. Projetos são onde o aprendizado se consolida — teoria sem prática esquece rápido.
Vamos revisar e construir.
Revisão rápida — Módulo 1
Variáveis e tipos
const nome = "Ricardo"; // string imutável
let pontos = 0; // número mutável
const ativo = true; // boolean
const endereco = null; // ausência intencional
let profissao; // undefined
// Template literal
console.log(`${nome} tem ${pontos} pontos.`);
Condicionais
const nota = 7.5;
if (nota >= 9) {
console.log("Excelente");
} else if (nota >= 6) {
console.log("Aprovado");
} else {
console.log("Reprovado");
}
// Ternário
const status = nota >= 6 ? "Aprovado" : "Reprovado";
Laços
// for clássico
for (let i = 0; i < 5; i++) {
console.log(i);
}
// for...of
const frutas = ["maçã", "banana", "laranja"];
for (const fruta of frutas) {
console.log(fruta);
}
// while
let tentativas = 3;
while (tentativas > 0) {
console.log(`Tentativas restantes: ${tentativas}`);
tentativas--;
}
Funções
// Declaração
function somar(a, b) { return a + b; }
// Expressão
const subtrair = function(a, b) { return a - b; };
// Arrow
const multiplicar = (a, b) => a * b;
// Parâmetros padrão
const saudar = (nome = "visitante") => `Olá, ${nome}!`;
Arrays
const numeros = [1, 2, 3, 4, 5];
const dobrados = numeros.map(n => n * 2);
const pares = numeros.filter(n => n % 2 === 0);
const soma = numeros.reduce((acc, n) => acc + n, 0);
Objetos
const usuario = {
nome: "Ana",
idade: 28,
saudar() {
return `Olá, sou ${this.nome}!`;
},
};
const { nome, idade } = usuario; // desestruturação
const copia = { ...usuario }; // spread
Escopo e Closures
function criarContador() {
let count = 0;
return {
incrementar: () => ++count,
valor: () => count,
};
}
const contador = criarContador();
contador.incrementar();
contador.incrementar();
console.log(contador.valor()); // 2
Tratamento de erros
function dividir(a, b) {
if (b === 0) throw new Error("Divisão por zero.");
return a / b;
}
try {
console.log(dividir(10, 0));
} catch (erro) {
console.log(`Erro: ${erro.message}`);
} finally {
console.log("Operação finalizada.");
}
Mini Projeto — Calculadora no Console
Agora vamos construir uma calculadora completa que aplica tudo do Módulo 1. Ela terá:
- Operações básicas: soma, subtração, multiplicação, divisão
- Operações avançadas: potência, resto, raiz quadrada
- Histórico de operações
- Validação de entrada com tratamento de erros
- Memória (guardar e recuperar um valor)
- Relatório final com estatísticas
Construiremos em partes, do mais simples ao mais complexo.
Parte 1 — Operações básicas
// Erros personalizados
class ErroCalculadora extends Error {
constructor(mensagem) {
super(mensagem);
this.name = "ErroCalculadora";
}
}
// Validação de entradas
function validarNumeros(...valores) {
for (const valor of valores) {
if (typeof valor !== "number" || isNaN(valor)) {
throw new ErroCalculadora(`"${valor}" não é um número válido.`);
}
}
}
// Operações — cada uma faz apenas uma coisa
const operacoes = {
somar: (a, b) => {
validarNumeros(a, b);
return a + b;
},
subtrair: (a, b) => {
validarNumeros(a, b);
return a - b;
},
multiplicar: (a, b) => {
validarNumeros(a, b);
return a * b;
},
dividir: (a, b) => {
validarNumeros(a, b);
if (b === 0) throw new ErroCalculadora("Divisão por zero não é permitida.");
return a / b;
},
potencia: (base, expoente) => {
validarNumeros(base, expoente);
return base ** expoente;
},
resto: (a, b) => {
validarNumeros(a, b);
if (b === 0) throw new ErroCalculadora("Divisão por zero não é permitida.");
return a % b;
},
raizQuadrada: (a) => {
validarNumeros(a);
if (a < 0) throw new ErroCalculadora("Não é possível calcular raiz de número negativo.");
return Math.sqrt(a);
},
};
Parte 2 — A fábrica da calculadora (closures + objetos)
function criarCalculadora() {
// Estado privado — acessível apenas pelos métodos
const historico = [];
let memoria = null;
let totalOperacoes = 0;
let totalErros = 0;
// Registra operação no histórico
function registrar(expressao, resultado) {
totalOperacoes++;
const entrada = {
numero: totalOperacoes,
expressao,
resultado,
horario: new Date().toLocaleTimeString("pt-BR"),
};
historico.push(entrada);
console.log(`[${entrada.numero}] ${expressao} = ${resultado}`);
return resultado;
}
// Executa uma operação com tratamento de erros
function executar(operacao, expressao, ...args) {
try {
const resultado = operacao(...args);
return registrar(expressao, resultado);
} catch (erro) {
totalErros++;
console.log(`❌ Erro: ${erro.message}`);
return null;
}
}
// Interface pública da calculadora
return {
somar(a, b) {
return executar(operacoes.somar, `${a} + ${b}`, a, b);
},
subtrair(a, b) {
return executar(operacoes.subtrair, `${a} - ${b}`, a, b);
},
multiplicar(a, b) {
return executar(operacoes.multiplicar, `${a} × ${b}`, a, b);
},
dividir(a, b) {
return executar(operacoes.dividir, `${a} ÷ ${b}`, a, b);
},
potencia(base, exp) {
return executar(operacoes.potencia, `${base} ^ ${exp}`, base, exp);
},
resto(a, b) {
return executar(operacoes.resto, `${a} % ${b}`, a, b);
},
raizQuadrada(a) {
return executar(operacoes.raizQuadrada, `√${a}`, a);
},
// Memória
salvarMemoria(valor) {
if (typeof valor !== "number" || isNaN(valor)) {
console.log("❌ Valor inválido para memória.");
return;
}
memoria = valor;
console.log(`💾 Memória salva: ${memoria}`);
},
recuperarMemoria() {
if (memoria === null) {
console.log("⚠️ Memória vazia.");
return null;
}
console.log(`💾 Memória: ${memoria}`);
return memoria;
},
limparMemoria() {
memoria = null;
console.log("💾 Memória limpa.");
},
// Histórico
verHistorico() {
if (historico.length === 0) {
console.log("Nenhuma operação realizada ainda.");
return;
}
console.log("\n📋 HISTÓRICO DE OPERAÇÕES:");
console.log("─".repeat(40));
historico.forEach(({ numero, expressao, resultado, horario }) => {
console.log(` [${numero}] ${horario} | ${expressao} = ${resultado}`);
});
console.log("─".repeat(40));
},
// Relatório final com estatísticas
relatorio() {
const resultados = historico.map(h => h.resultado).filter(r => r !== null);
const maior = resultados.length > 0 ? Math.max(...resultados) : null;
const menor = resultados.length > 0 ? Math.min(...resultados) : null;
const media = resultados.length > 0
? (resultados.reduce((acc, r) => acc + r, 0) / resultados.length).toFixed(2)
: null;
console.log("\n📊 RELATÓRIO DA SESSÃO:");
console.log("═".repeat(40));
console.log(` Total de operações : ${totalOperacoes}`);
console.log(` Operações com erro : ${totalErros}`);
console.log(` Operações válidas : ${totalOperacoes - totalErros}`);
console.log(` Maior resultado : ${maior}`);
console.log(` Menor resultado : ${menor}`);
console.log(` Média dos resultados: ${media}`);
console.log(` Memória atual : ${memoria ?? "vazia"}`);
console.log("═".repeat(40));
},
};
}
Parte 3 — Usando a calculadora
const calc = criarCalculadora();
console.log("🔢 CALCULADORA JAVASCRIPT\n");
// Operações básicas
calc.somar(10, 5); // [1] 10 + 5 = 15
calc.subtrair(20, 8); // [2] 20 - 8 = 12
calc.multiplicar(6, 7); // [3] 6 × 7 = 42
calc.dividir(100, 4); // [4] 100 ÷ 4 = 25
// Operações avançadas
calc.potencia(2, 10); // [5] 2 ^ 10 = 1024
calc.resto(17, 5); // [6] 17 % 5 = 2
calc.raizQuadrada(144); // [7] √144 = 12
// Testando erros
calc.dividir(10, 0); // ❌ Divisão por zero
calc.raizQuadrada(-9); // ❌ Raiz de negativo
calc.somar("abc", 5); // ❌ Valor inválido
// Memória
calc.salvarMemoria(calc.somar(3, 7)); // salva 10
calc.recuperarMemoria(); // 💾 Memória: 10
calc.multiplicar(calc.recuperarMemoria(), 5); // 10 × 5 = 50
calc.limparMemoria();
// Histórico e relatório
calc.verHistorico();
calc.relatorio();
Parte 4 — Saída esperada no console
🔢 CALCULADORA JAVASCRIPT
[1] 10 + 5 = 15
[2] 20 - 8 = 12
[3] 6 × 7 = 42
[4] 100 ÷ 4 = 25
[5] 2 ^ 10 = 1024
[6] 17 % 5 = 2
[7] √144 = 12
❌ Erro: Divisão por zero não é permitida.
❌ Erro: Não é possível calcular raiz de número negativo.
❌ Erro: "abc" não é um número válido.
[8] 3 + 7 = 10
💾 Memória salva: 10
💾 Memória: 10
[9] 10 × 5 = 50
💾 Memória limpa.
📋 HISTÓRICO DE OPERAÇÕES:
────────────────────────────────────────
[1] 10:32:15 | 10 + 5 = 15
[2] 10:32:15 | 20 - 8 = 12
[3] 10:32:15 | 6 × 7 = 42
[4] 10:32:15 | 100 ÷ 4 = 25
[5] 10:32:15 | 2 ^ 10 = 1024
[6] 10:32:15 | 17 % 5 = 2
[7] 10:32:15 | √144 = 12
[8] 10:32:15 | 3 + 7 = 10
[9] 10:32:15 | 10 × 5 = 50
────────────────────────────────────────
📊 RELATÓRIO DA SESSÃO:
════════════════════════════════════════
Total de operações : 12
Operações com erro : 3
Operações válidas : 9
Maior resultado : 1024
Menor resultado : 2
Média dos resultados: 243.56
Memória atual : vazia
════════════════════════════════════════
O que este projeto exercitou
| Conceito | Onde apareceu |
|---|---|
const e let |
Estado interno da calculadora |
| Condicionais | Validações e tratamento de casos especiais |
| Funções e arrow functions | Todas as operações e helpers |
| Objetos e métodos | Interface pública e objeto operacoes |
| Arrays e métodos | Histórico, map, filter, reduce |
| Desestruturação | forEach no histórico |
| Spread operator | Math.max(...resultados) |
| Escopo | Estado privado da calculadora |
| Closures | historico, memoria, totalOperacoes privados |
| Classes de erro | ErroCalculadora |
| try/catch/finally | executar() |
| Template literals | Todas as mensagens formatadas |
Desafio final do Módulo 1
Expanda a calculadora com pelo menos duas das funcionalidades abaixo:
- Método
desfazer()que remove a última operação do histórico - Método
filtrarHistorico(operador)que retorna apenas operações de um tipo (ex: só somas) - Método
exportarHistorico()que retorna o histórico como string formatada - Suporte a cálculos encadeados:
calc.somar(5, 3).multiplicar(2)retornando16 - Método
limpar()que zera todo o estado da calculadora
Conclusão do Módulo 1
Parabéns. Você completou o primeiro módulo da série. Em dez artigos você aprendeu:
- Variáveis, tipos e operadores
- Estruturas condicionais e switch
- Laços de repetição
- Funções em todas as suas formas
- Arrays com map, filter e reduce
- Objetos, métodos e this
- Desestruturação, spread e rest
- Escopo, hoisting e closures
- Tratamento de erros robusto
- Como unir tudo em um projeto real
No próximo módulo saímos do console e entramos no navegador — vamos aprender a manipular o DOM, reagir a eventos e criar interfaces interativas com JavaScript puro.
📌 Próximo artigo: Aula 11 — O que é o DOM e como o JavaScript interage com o HTML 🎯 Início do Módulo 2 — JavaScript no Navegador
📚 Fontes e Referências
- MDN Web Docs — JavaScript Guide: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide
- JavaScript.info — Guia completo: https://javascript.info
- Eloquent JavaScript — Marijn Haverbeke: https://eloquentjavascript.net
- You Don't Know JS — Kyle Simpson: https://github.com/getify/You-Dont-Know-JS
- Clean Code — Robert C. Martin (Alta Books)
- Airbnb JavaScript Style Guide: https://github.com/airbnb/javascript
- freeCodeCamp — JavaScript Algorithms and Data Structures: https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/