Operadores aritméticos, lógicos e de atribuição

1. Operadores Aritméticos Básicos

Os operadores aritméticos fundamentais em JavaScript são adição (+), subtração (-), multiplicação (*) e divisão (/). Eles funcionam exatamente como na matemática tradicional, mas com algumas particularidades da linguagem.

// Operadores aritméticos básicos
const a = 15;
const b = 4;

console.log(a + b);  // 19 (adição)
console.log(a - b);  // 11 (subtração)
console.log(a * b);  // 60 (multiplicação)
console.log(a / b);  // 3.75 (divisão)

O operador de módulo (%) retorna o resto de uma divisão, sendo extremamente útil para validações como verificar se um número é par ou ímpar:

// Módulo para validação de par/ímpar
const numero = 7;
console.log(numero % 2 === 0 ? 'Par' : 'Ímpar'); // 'Ímpar'

// Resto de divisão
console.log(10 % 3); // 1
console.log(15 % 5); // 0

A exponenciação (**) foi introduzida no ES2016 e é equivalente ao método Math.pow():

// Exponenciação
console.log(2 ** 3);  // 8 (2³)
console.log(5 ** 2);  // 25 (5²)
console.log(10 ** 0); // 1

// Precedência de operadores com parênteses
const resultado = (2 + 3) * 4 ** 2; // 5 * 16 = 80
console.log(resultado);

2. Operadores Aritméticos Avançados e Casos Especiais

O incremento (++) e decremento (--) podem ser usados nas formas pré-fixada e pós-fixada, com comportamentos distintos:

// Incremento e decremento
let contador = 5;

// Pós-fixado: usa o valor atual, depois incrementa
console.log(contador++); // 5
console.log(contador);   // 6

// Pré-fixado: incrementa, depois usa o novo valor
console.log(++contador); // 7

O operador unário (+) converte strings para números, enquanto o operador unário (-) inverte o sinal:

// Operador unário
const texto = "42";
console.log(+texto);        // 42 (converte string para número)
console.log(-texto);        // -42 (inverte o sinal)
console.log(+true);         // 1
console.log(-false);        // -0

Operações com NaN e Infinity seguem regras específicas:

// NaN e Infinity em operações
console.log(0 / 0);         // NaN
console.log(Infinity + 1);  // Infinity
console.log(NaN + 5);       // NaN
console.log(Infinity - Infinity); // NaN
console.log(10 / 0);        // Infinity

3. Operadores de Atribuição

A atribuição simples (=) é a base, mas os operadores compostos permitem operações mais concisas:

// Atribuição simples
let valor = 10;

// Atribuição composta
valor += 5;   // valor = valor + 5 → 15
valor -= 3;   // valor = valor - 3 → 12
valor *= 2;   // valor = valor * 2 → 24
valor /= 4;   // valor = valor / 4 → 6
valor %= 5;   // valor = valor % 5 → 1
valor **= 3;  // valor = valor ** 3 → 1

Em React, os operadores de atribuição são frequentemente usados com useState:

// Exemplo prático em React com useState
function Contador() {
  const [contador, setContador] = useState(0);

  function incrementar() {
    setContador(prev => prev + 1); // equivalente a += 1
  }

  function adicionar(valor) {
    setContador(prev => prev + valor); // equivalente a += valor
  }
}

4. Operadores Lógicos: &&, || e !

O operador AND (&&) utiliza curto-circuito: se o primeiro operando for falsy, retorna-o sem avaliar o segundo:

// AND lógico e curto-circuito
const usuario = { nome: 'João', admin: true };

// Renderização condicional no React
function PainelAdmin({ usuario }) {
  return (
    <div>
      {usuario.admin && <BotaoAdmin />}
    </div>
  );
}

O operador OR (||) retorna o primeiro valor truthy, sendo útil para valores padrão:

// OR lógico para fallback
function saudacao(nome) {
  return `Olá, ${nome || 'visitante'}`;
}

console.log(saudacao('Maria')); // 'Olá, Maria'
console.log(saudacao(''));      // 'Olá, visitante'

O operador NOT (!) inverte o valor booleano, e a dupla negação (!!) converte qualquer valor para boolean:

// NOT lógico e dupla negação
console.log(!true);    // false
console.log(!0);       // true
console.log(!'');      // true

// Dupla negação para conversão booleana
console.log(!!'texto'); // true
console.log(!!0);       // false
console.log(!!null);    // false

5. Operadores Lógicos Avançados e Nullish Coalescing

O operador de coalescência nula (??) difere do || por tratar apenas null e undefined como valores a serem substituídos:

// Nullish coalescing vs OR lógico
const valor1 = 0;
const valor2 = '';

console.log(valor1 || 10);  // 10 (0 é falsy)
console.log(valor1 ?? 10);  // 0 (0 não é null/undefined)

console.log(valor2 || 'padrão'); // 'padrão' ('' é falsy)
console.log(valor2 ?? 'padrão'); // '' ('' não é null/undefined)

O encadeamento opcional (?.) permite acessar propriedades de objetos aninhados sem erro:

// Encadeamento opcional com operadores lógicos
const usuario = {
  perfil: {
    endereco: {
      cidade: 'São Paulo'
    }
  }
};

// Acesso seguro a propriedades aninhadas
console.log(usuario?.perfil?.endereco?.cidade); // 'São Paulo'
console.log(usuario?.preferencias?.tema ?? 'claro'); // 'claro'

// Combinação em Node.js
function processarConfig(config) {
  return config?.database?.host ?? 'localhost';
}

6. Operadores de Comparação e Coerção Implícita

A diferença entre == e === é crucial: == faz coerção de tipos, enquanto === compara valor e tipo:

// == vs === com operadores aritméticos
console.log(5 == '5');   // true (coerção de tipo)
console.log(5 === '5');  // false (tipos diferentes)
console.log(0 == false); // true
console.log(0 === false);// false

// Operadores relacionais com coerção
console.log('10' > 5);    // true (string '10' convertida para número)
console.log('abc' < 5);   // false (NaN < 5 é false)

Comparação de objetos e arrays requer atenção especial:

// Comparação de objetos e arrays
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const obj1 = { a: 1 };
const obj2 = { a: 1 };

console.log(arr1 == arr2);  // false (comparação por referência)
console.log(obj1 === obj2); // false (comparação por referência)

7. Aplicações Práticas em Node.js e React

Em APIs Node.js, operadores aritméticos são usados para cálculos de negócio:

// Cálculos em API Node.js
function calcularPrecoComDesconto(preco, descontoPercentual) {
  const desconto = preco * (descontoPercentual / 100);
  const precoFinal = preco - desconto;
  return Number(precoFinal.toFixed(2));
}

// Lógica de impostos
function calcularImposto(valor, taxa) {
  return valor * (1 + taxa);
}

Em componentes React, operadores lógicos controlam renderização e eventos:

// Componente React com lógica condicional
function ProdutoCard({ produto, desconto }) {
  const precoFinal = desconto 
    ? produto.preco - (produto.preco * desconto / 100)
    : produto.preco;

  return (
    <div>
      <h3>{produto.nome}</h3>
      {desconto && <span className="desconto">-{desconto}%</span>}
      <p>Preço: R$ {precoFinal.toFixed(2)}</p>
      {!produto.estoque && <p className="esgotado">Esgotado</p>}
    </div>
  );
}

Atualização de estado com operadores de atribuição em hooks:

// useReducer com operadores de atribuição
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENTAR':
      return { ...state, contador: state.contador + 1 };
    case 'ADICIONAR':
      return { ...state, total: state.total += action.valor };
    case 'RESET':
      return { ...state, contador: 0, total: 0 };
    default:
      return state;
  }
}

Referências