Em JavaScript, booleanos são o tipo de dado que representa verdadeiro ou falso, mas a linguagem vai além: qualquer valor pode ser interpretado como verdadeiro ou falso em um contexto booleano. Esse conceito é fundamental para entender condicionais, loops e operadores lógicos. Nesta aula, vamos mergulhar nos valores truthy e falsy, aprender como converter valores para booleanos, explorar o curto-circuito em operadores lógicos e discutir boas práticas para evitar bugs sutis.

Dominar esses conceitos é essencial para escrever código JavaScript expressivo e eficiente, além de evitar comportamentos inesperados. Vamos começar!

Valores falsy

Em JavaScript, um valor falsy é aquele que é considerado false quando avaliado em um contexto booleano. Existem exatamente 6 valores falsy (além de false propriamente dito):

  • false
  • 0 (e -0)
  • '' (string vazia)
  • null
  • undefined
  • NaN

Qualquer outro valor é considerado truthy, incluindo objetos vazios ({}), arrays vazios ([]), strings não vazias ('false'), números diferentes de zero (positivos ou negativos), e até mesmo Infinity.

Exemplo prático:

if (0) {
  console.log('nunca executa');
} else {
  console.log('0 é falsy'); // saída
}

if ('') {
  console.log('nunca executa');
} else {
  console.log('string vazia é falsy'); // saída
}

if ([]) {
  console.log('array vazio é truthy'); // saída
}

if ({}) {
  console.log('objeto vazio é truthy'); // saída
}

É importante lembrar que null e undefined são falsy, mas null == undefined é true, enquanto null === undefined é false.

Conversão para booleano

Podemos converter explicitamente um valor para booleano usando a função Boolean() ou o operador de dupla negação !!. A conversão implícita ocorre em contextos como if, while, for e operadores lógicos.

Exemplos de conversão explícita:

console.log(Boolean(0)); // false
console.log(Boolean('')); // false
console.log(Boolean('false')); // true (string não vazia)
console.log(Boolean([])); // true

// Usando !!
console.log(!!0); // false
console.log(!!'hello'); // true
console.log(!!null); // false

A conversão implícita acontece, por exemplo, em um if:

let nome = '';
if (nome) {
  console.log('Nome fornecido');
} else {
  console.log('Nome não fornecido'); // executa, pois '' é falsy
}

Outro contexto comum é em loops:

let valor = 10;
while (valor) {
  console.log(valor);
  valor--;
}
// Quando valor chega a 0, o loop para, pois 0 é falsy.

Curto-circuito

Os operadores lógicos && (AND) e || (OR) utilizam curto-circuito: eles avaliam a expressão da esquerda para a direita e param assim que o resultado é determinado. O valor retornado é o último valor avaliado, não necessariamente um booleano.

Operador OR (||): Retorna o primeiro valor truthy, ou o último valor se todos forem falsy.

console.log(0 || 'texto'); // 'texto' (primeiro truthy)
console.log(false || 0 || ''); // '' (último, todos falsy)
console.log('A' || 'B'); // 'A' (primeiro truthy)

Operador AND (&&): Retorna o primeiro valor falsy, ou o último valor se todos forem truthy.

console.log(1 && 2 && 3); // 3 (todos truthy, retorna o último)
console.log(1 && 0 && 3); // 0 (primeiro falsy)
console.log(null && 'qualquer'); // null (primeiro falsy)

O curto-circuito é frequentemente usado para atribuições condicionais e para evitar erros:

// Atribuição com valor padrão
let nome = usuarioInput || 'visitante';

// Execução condicional
objeto && objeto.metodo(); // só chama metodo se objeto for truthy

Cuidado: o curto-circuito pode causar efeitos colaterais se a expressão tiver chamadas de função.

Boas práticas

Ao trabalhar com truthy/falsy, algumas práticas ajudam a evitar bugs:

  • Seja explícito quando necessário: Em comparações, prefira usar === a == para evitar conversões implícitas inesperadas. Por exemplo, 0 == false é true, mas 0 === false é false.
  • Evite usar valores truthy/falsy para verificar se uma variável foi definida: Use typeof ou in para verificar existência, pois null e undefined são falsy, mas uma string vazia também é falsy e pode ser um valor válido.
  • Use !! para converter para booleano de forma concisa: É uma prática comum e legível.
  • Cuidado com 0 e strings vazias: Às vezes queremos tratar 0 como um valor válido. Nesse caso, verifique explicitamente if (valor !== null && valor !== undefined).
  • Prefira operadores lógicos com curto-circuito para valores padrão: const nome = input || 'padrão'; é mais limpo que if (!input) { nome = 'padrão'; } else { nome = input; }.

Exemplo de boas práticas:

// Ruim: pode tratar 0 como ausente
function cumprimentar(idade) {
  if (!idade) {
    console.log('Idade não informada');
  } else {
    console.log('Idade: ' + idade);
  }
}
cumprimentar(0); // 'Idade não informada' (inesperado)

// Melhor: verificar undefined/null explicitamente
function cumprimentarMelhor(idade) {
  if (idade === undefined || idade === null) {
    console.log('Idade não informada');
  } else {
    console.log('Idade: ' + idade);
  }
}
cumprimentarMelhor(0); // 'Idade: 0'

Referências

Exercícios

  1. Quais são os 6 valores falsy em JavaScript? Liste-os.
  2. ✓ Resposta: Os 6 valores falsy são: false, 0 (e -0), '' (string vazia), null, undefined e NaN.
  3. Qual a diferença entre usar Boolean() e !! para converter um valor para booleano? Dê um exemplo.
  4. ✓ Resposta: Ambos convertem o valor para booleano. Boolean(valor) é uma função explícita. !!valor usa a negação dupla: a primeira negação converte para booleano invertido, a segunda inverte de volta. Exemplo: Boolean(0) retorna false; !!0 também retorna false. Não há diferença prática no resultado.
  5. Explique o que é curto-circuito no operador ||. Dê um exemplo de uso para valor padrão.
  6. ✓ Resposta: O operador || avalia da esquerda para a direita e retorna o primeiro valor truthy, ou o último se todos forem falsy. Exemplo: const nome = usuarioInput || 'Visitante'; Se usuarioInput for uma string vazia (falsy), nome receberá 'Visitante'.
  7. O que será exibido no console? console.log(0 && 'texto'); Justifique.
  8. ✓ Resposta: Será exibido 0. O operador && retorna o primeiro valor falsy. Como 0 é falsy, ele é retornado imediatamente sem avaliar o segundo operando.
  9. Escreva uma função que recebe um valor e retorna 'truthy' ou 'falsy' usando o operador ternário e a conversão booleana.
  10. ✓ Resposta:
    function verificarTruthy(valor) {
      return valor ? 'truthy' : 'falsy';
    }
    
    console.log(verificarTruthy(0)); // 'falsy'
    console.log(verificarTruthy('a')); // 'truthy'