O Poder de Combinar Condições

Na vida real, raramente tomamos decisões baseadas em apenas uma condição. Por exemplo:

  • "Vou à praia SE estiver sol E for fim de semana"
  • "Aceito o emprego SE o salário for bom OU a localização for conveniente"
  • "NÃO vou sair se estiver chovendo"

Os operadores lógicos permitem combinar múltiplas condições para criar lógicas mais complexas e realistas.

Operador AND (&&)

O operador && (E lógico) retorna true apenas quando TODAS as condições forem verdadeiras:

console.log(true && true);      // true
console.log(true && false);     // false
console.log(false && true);     // false
console.log(false && false);    // false

Exemplo Prático: Validação de Acesso

let temIngresso = true;
let temIdade = true;

let podeEntrar = temIngresso && temIdade;
console.log(podeEntrar);  // true - tem AMBOS os requisitos

temIdade = false;
podeEntrar = temIngresso && temIdade;
console.log(podeEntrar);  // false - falta um requisito

Exemplo: Validação de Senha

let senha = "abc123";
let temTamanhoMinimo = senha.length >= 6;
let temNumero = senha.includes("1") || senha.includes("2") || senha.includes("3");

let senhaValida = temTamanhoMinimo && temNumero;
console.log(senhaValida);  // true - atende todos os critérios

Operador OR (||)

O operador || (OU lógico) retorna true se PELO MENOS UMA condição for verdadeira:

console.log(true || true);      // true
console.log(true || false);     // true
console.log(false || true);     // true
console.log(false || false);    // false

Exemplo Prático: Múltiplas Formas de Pagamento

let temDinheiro = false;
let temCartao = true;
let temPix = false;

let podeComprar = temDinheiro || temCartao || temPix;
console.log(podeComprar);  // true - tem pelo menos uma forma de pagamento

Exemplo: Sistema de Desconto

let ehEstudante = true;
let ehIdoso = false;
let ehFuncionario = false;

let temDesconto = ehEstudante || ehIdoso || ehFuncionario;
console.log(temDesconto);  // true - pelo menos um critério atendido

Operador NOT (!)

O operador ! (NÃO lógico) inverte o valor booleano:

console.log(!true);     // false
console.log(!false);    // true
console.log(!!true);    // true (dupla negação)

Exemplo Prático: Negação de Condições

let estaLogado = false;
let precisaLogar = !estaLogado;
console.log(precisaLogar);  // true - usuário precisa fazer login

let temPermissao = false;
let acessoNegado = !temPermissao;
console.log(acessoNegado);  // true - acesso deve ser negado

Combinando Múltiplos Operadores

Podemos criar lógicas complexas combinando diferentes operadores:

let idade = 25;
let temCarteira = true;
let temCarro = true;

// Pode dirigir SE tem idade >= 18 E tem carteira E tem carro
let podeDirigir = (idade >= 18) && temCarteira && temCarro;
console.log(podeDirigir);  // true

// Precisa de transporte SE NÃO pode dirigir OU NÃO tem carro
let precisaTransporte = !podeDirigir || !temCarro;
console.log(precisaTransporte);  // false

Exemplo: Sistema de Aprovação Escolar

let notaFinal = 7.5;
let frequencia = 80;
let trabalhoEntregue = true;

// Aprovado SE (nota >= 7 E frequência >= 75) E trabalho entregue
let aprovado = (notaFinal >= 7 && frequencia >= 75) && trabalhoEntregue;
console.log(aprovado);  // true

Valores Truthy e Falsy

JavaScript converte automaticamente valores para booleano quando necessário. Isso é fundamental para entender o comportamento dos operadores lógicos.

Valores Falsy (considerados false)

Existem exatamente 6 valores falsy em JavaScript:

console.log(!false);        // true - false é falsy
console.log(!0);            // true - 0 é falsy
console.log(!"");           // true - string vazia é falsy
console.log(!null);         // true - null é falsy
console.log(!undefined);    // true - undefined é falsy
console.log(!NaN);          // true - NaN é falsy

Valores Truthy (considerados true)

TODOS os outros valores são truthy:

console.log(!42);           // false - número diferente de 0 é truthy
console.log(!"texto");      // false - string não-vazia é truthy
console.log(!true);         // false - true é truthy
console.log(![]);           // false - array é truthy
console.log(!{});           // false - objeto é truthy
console.log(!-1);           // false - número negativo é truthy

Operadores Lógicos com Valores Não-Booleanos

Os operadores && e || não apenas retornam true ou false - eles retornam um dos valores originais!

Comportamento do OR (||)

O operador || retorna o primeiro valor truthy ou o último valor:

console.log(null || "usuário");         // "usuário"
console.log("Ana" || "visitante");      // "Ana"
console.log(0 || 100);                  // 100
console.log("" || "texto padrão");      // "texto padrão"
console.log(false || false || "oi");    // "oi"

Uso Prático: Valores Padrão

let nomeUsuario = "";
let nomeExibicao = nomeUsuario || "Visitante";
console.log(nomeExibicao);  // "Visitante"

nomeUsuario = "Maria";
nomeExibicao = nomeUsuario || "Visitante";
console.log(nomeExibicao);  // "Maria"

Comportamento do AND (&&)

O operador && retorna o primeiro valor falsy ou o último valor:

console.log(true && "oi");              // "oi"
console.log(1 && 2 && 3);               // 3
console.log(0 && "qualquer coisa");     // 0
console.log(null && true);              // null

Uso Prático: Execução Condicional

let usuario = { nome: "João", premium: true };

// Executa segunda parte apenas se primeira for truthy
let mensagem = usuario.premium && "Acesso Premium Ativo";
console.log(mensagem);  // "Acesso Premium Ativo"

usuario.premium = false;
mensagem = usuario.premium && "Acesso Premium Ativo";
console.log(mensagem);  // false

Operador de Coalescência Nula (??)

Este é um operador moderno que trata especificamente null e undefined:

// OR tradicional trata todos os falsy
console.log(0 || 100);          // 100 (0 é falsy)
console.log("" || "texto");     // "texto" (string vazia é falsy)

// ?? trata apenas null e undefined
console.log(0 ?? 100);          // 0 (0 não é null nem undefined)
console.log("" ?? "texto");     // "" (string vazia não é null nem undefined)
console.log(null ?? 100);       // 100 (null é tratado)
console.log(undefined ?? 50);   // 50 (undefined é tratado)

Quando Usar ?? vs ||

let contador = 0;

// ❌ Problema com ||
let resultado1 = contador || 10;
console.log(resultado1);  // 10 (mas 0 era um valor válido!)

// ✅ Solução com ??
let resultado2 = contador ?? 10;
console.log(resultado2);  // 0 (preserva valores válidos como 0)

Avaliação de Curto-Circuito

Os operadores && e || usam avaliação de curto-circuito - param assim que o resultado é determinado:

Com OR (||)

// Se a primeira parte é true, a segunda NÃO é avaliada
console.log(true || console.log("Não executado"));  // true (não imprime nada)

// Se a primeira parte é false, a segunda É avaliada
console.log(false || console.log("Executado"));     // undefined (imprime "Executado")

Com AND (&&)

// Se a primeira parte é false, a segunda NÃO é avaliada
console.log(false && console.log("Não executado")); // false (não imprime nada)

// Se a primeira parte é true, a segunda É avaliada
console.log(true && console.log("Executado"));      // undefined (imprime "Executado")

Por Que Isso É Útil?

let usuario = null;

// Evita erro ao acessar propriedade de null
let nome = usuario && usuario.nome;
console.log(nome);  // null (não tenta acessar usuario.nome)

usuario = { nome: "Carlos" };
nome = usuario && usuario.nome;
console.log(nome);  // "Carlos"

Precedência de Operadores

Quando múltiplos operadores aparecem juntos, há uma ordem de avaliação:

  1. ! (NOT) - maior precedência
  2. Operadores de comparação (>, <, ==, ===, etc.)
  3. && (AND)
  4. || (OR) - menor precedência
// Como JavaScript avalia:
console.log(true || false && false);
// 1. Avalia false && false = false
// 2. Avalia true || false = true
// Resultado: true

// Use parênteses para clareza:
console.log((true || false) && false);  // false
console.log(true || (false && false));  // true

Exemplo Complexo

let a = 10;
let b = 5;
let c = 0;

let resultado = a > b && b > c || c === 0;
// 1. a > b = true
// 2. b > c = true
// 3. true && true = true
// 4. c === 0 = true
// 5. true || true = true
console.log(resultado);  // true

// Com parênteses para clareza:
resultado = (a > b && b > c) || (c === 0);
console.log(resultado);  // true

Exemplos Práticos

Exemplo 1: Sistema de Login

let usuarioDigitado = "admin";
let senhaDigitada = "1234";
let usuarioCorreto = "admin";
let senhaCorreta = "1234";

// Login bem-sucedido SE usuário correto E senha correta
let loginSucesso = (usuarioDigitado === usuarioCorreto) && 
                   (senhaDigitada === senhaCorreta);

console.log("Login permitido:", loginSucesso);  // true

// Testando com dados incorretos
usuarioDigitado = "admin";
senhaDigitada = "errada";

loginSucesso = (usuarioDigitado === usuarioCorreto) && 
               (senhaDigitada === senhaCorreta);

console.log("Login permitido:", loginSucesso);  // false

Exemplo 3: Sistema de Desconto em Loja

let valorCompra = 150;
let ehClienteVIP = false;
let ehPrimeiraCompra = true;
let temCupom = false;

// Desconto de 20% SE valor >= 100 E (é VIP OU primeira compra OU tem cupom)
let temDesconto = (valorCompra >= 100) && 
                  (ehClienteVIP || ehPrimeiraCompra || temCupom);

console.log("Tem desconto:", temDesconto);  // true

if (temDesconto) {
    let desconto = valorCompra * 0.20;
    let valorFinal = valorCompra - desconto;
    console.log("Valor original: R$", valorCompra);
    console.log("Desconto: R$", desconto);
    console.log("Valor final: R$", valorFinal);
}

Exemplo 3: Controle de Acesso a Conteúdo

let idadeUsuario = 16;
let temAutorizacaoPais = false;
let ehAssinante = true;

// Pode acessar SE (idade >= 18 OU tem autorização dos pais) E é assinante
let podeAcessar = ((idadeUsuario >= 18) || temAutorizacaoPais) && ehAssinante;

console.log("Pode acessar:", podeAcessar);  // false

// Com autorização dos pais
temAutorizacaoPais = true;
podeAcessar = ((idadeUsuario >= 18) || temAutorizacaoPais) && ehAssinante;
console.log("Pode acessar: ", podeAcessar);  // true

Exemplo 4: Sistema de Notas Escolares

let nota1 = 7.5;
let nota2 = 8.0;
let nota3 = 6.5;
let frequencia = 85;

let media = (nota1 + nota2 + nota3) / 3;
let frequenciaMinima = 75;
let notaMinima = 7.0;

// Aprovado SE média >= 7 E frequência >= 75
let aprovado = (media >= notaMinima) && (frequencia >= frequenciaMinima);

console.log("Média:", media.toFixed(2));
console.log("Frequência:", frequencia. "%");
console.log("Aprovado:", aprovado);  // true

Boas Práticas

✅ Operadores de Comparação

  1. Use sempre === e !== para evitar conversões inesperadas
  2. Cuidado com null e undefined em comparações
  3. Lembre-se: NaN não é igual a nada, nem a si mesmo
  4. Strings são comparadas em ordem lexicográfica
  5. Use parênteses para deixar comparações complexas mais claras

✅ Operadores Lógicos

  1. && (AND): todas as condições devem ser verdadeiras
  2. || (OR): pelo menos uma condição deve ser verdadeira
  3. ! (NOT): inverte o valor booleano
  4. Entenda valores truthy e falsy para evitar surpresas
  5. Use ?? quando quiser tratar apenas null e undefined

✅ Precedência

  1. ! tem a maior precedência
  2. Comparações vêm depois
  3. && antes de ||
  4. Use parênteses quando houver dúvida

⚠️ Erros Comuns a Evitar

// ❌ ERRADO: Usar == em vez de ===
if (idade == "18") { }  // Compara número com string

// ✅ CORRETO: Usar ===
if (idade === 18) { }

// ❌ ERRADO: Esquecer parênteses em lógicas complexas
if (a > b && c > d || e > f) { }  // Confuso!

// ✅ CORRETO: Usar parênteses
if ((a > b && c > d) || e > f) { }  // Claro!

// ❌ ERRADO: Assumir que valores são booleanos
if (usuario) { }  // undefined é falsy!

// ✅ CORRETO: Verificar explicitamente
if (usuario !== null && usuario !== undefined) { }

Próximos passos

Na próxima aula você aprenderá sobre como usar esses operadores para mudar o fluxo de execução do código:

  • Como executar código condicionalmente
  • Estruturas else if para múltiplas condições
  • O operador ternário para decisões concisas
  • A estrutura switch para múltiplas opções

Quanto mais você praticar, mais natural se tornará o processo de criar lógicas complexas!