Operadores y expresiones

Aprende los operadores de JavaScript: aritméticos, de comparación, lógicos, de asignación y el operador ternario.

Los operadores son los símbolos que le dicen a JavaScript qué hacer con los valores. Sumar, comparar, combinar condiciones — todo pasa por operadores.


Operadores aritméticos

const a = 10;
const b = 3;

a + b   // 13  — suma
a - b   // 7   — resta
a * b   // 30  — multiplicación
a / b   // 3.333... — división
a % b   // 1   — módulo (resto de la división)
a ** b  // 1000 — potencia (10³)

El módulo (%) es muy útil para saber si un número es par o impar:

const numero = 7;
const esPar = numero % 2 === 0; // false — 7 no es divisible entre 2

Operadores de asignación

let x = 10;

x += 5;  // x = x + 5  → 15
x -= 3;  // x = x - 3  → 12
x *= 2;  // x = x * 2  → 24
x /= 4;  // x = x / 4  → 6
x **= 2; // x = x ** 2 → 36
x %= 5;  // x = x % 5  → 1

Incremento y decremento

let i = 0;
i++;  // i = i + 1 → 1 (postfijo: devuelve el valor antes de incrementar)
++i;  // i = i + 1 → 2 (prefijo: devuelve el valor después de incrementar)
i--;  // i = i - 1 → 1

Operadores de comparación

Devuelven siempre true o false:

5 > 3     // true  — mayor que
5 < 3     // false — menor que
5 >= 5    // true  — mayor o igual
5 <= 4    // false — menor o igual

5 == '5'  // true  — igualdad débil (compara valor, convierte tipos)
5 === '5' // false — igualdad estricta (compara valor Y tipo)
5 != '5'  // false — desigualdad débil
5 !== '5' // true  — desigualdad estricta

Siempre usa === y !==. La igualdad débil (==) hace conversiones de tipo automáticas que producen resultados difíciles de predecir:

0 == false    // true  — ¿?
'' == false   // true  — ¿?
null == undefined // true — ¿?

Operadores lógicos

Combinan condiciones booleanas:

// AND (&&) — true si AMBOS son true
true && true   // true
true && false  // false

// OR (||) — true si AL MENOS UNO es true
true || false  // true
false || false // false

// NOT (!) — invierte el booleano
!true   // false
!false  // true
!!valor // convierte a booleano (doble negación)

Cortocircuito: && y ||

JavaScript evalúa de izquierda a derecha y para en cuanto puede determinar el resultado:

// && devuelve el primer valor falsy, o el último si todos son truthy
'texto' && 42       // 42
null && 'algo'      // null — para aquí, no evalúa 'algo'

// || devuelve el primer valor truthy, o el último si todos son falsy
null || 'por defecto'   // 'por defecto'
'valor' || 'por defecto' // 'valor' — para aquí

// Uso práctico: valores por defecto
const nombre = usuarioIngresado || 'Invitado';

Nullish coalescing (??)

Similar a ||, pero solo activa el valor por defecto si el primero es null o undefined (no si es 0 o ''):

const descuento = 0;

descuento || 10   // 10  — incorrecto: 0 es falsy
descuento ?? 10   // 0   — correcto: 0 no es null ni undefined

Operador ternario

Una forma compacta de escribir un if/else en una línea:

condición ? valorSiTrue : valorSiFalse
const edad = 20;
const acceso = edad >= 18 ? 'permitido' : 'denegado';
// acceso = 'permitido'

const saludo = hora < 12 ? 'Buenos días' : hora < 20 ? 'Buenas tardes' : 'Buenas noches';

No anides ternarios más de un nivel — se vuelven ilegibles rápidamente. Usa if/else para lógica compleja.


Operador de encadenamiento opcional (?.)

Cuando lees una propiedad de un objeto, JavaScript lo hace por tramos: primero evalúa el primer segmento, luego el segundo, luego el tercero… Si en cualquier punto se encuentra un null o undefined, lanza un TypeError y se detiene.

const usuario = {
  nombre: 'Ana',
  perfil: {
    avatar: 'foto.jpg',
    direccion: null
  }
};

// Acceso simple — funciona
usuario.nombre          // 'Ana'

// Acceso anidado — funciona porque perfil existe
usuario.perfil.avatar   // 'foto.jpg'

// Acceso sobre null — EXPLOTA
usuario.perfil.direccion.ciudad // TypeError: Cannot read properties of null

El error ocurre porque JavaScript intenta leer .ciudad en null. No sabe parar solo.

?. detiene el tramo en el momento del fallo

Pones ?. justo antes del tramo que puede no existir. Si el valor de la izquierda es null o undefined, toda la expresión devuelve undefined sin lanzar error:

usuario.perfil?.direccion?.ciudad  // undefined — sin error

Cada ?. es un punto de control independiente. El acceso se detiene en el primer tramo que falla:

const respuesta = {
  data: null
};

respuesta.data?.usuario?.nombre     // undefined — data es null, para aquí
respuesta.data?.usuario?.edad       // undefined — igual, para en data
respuesta.noExiste?.propiedad       // undefined — noExiste no está definida

También funciona con arrays y métodos

const pedido = {
  items: ['pizza', 'refresco']
};

pedido.items?.[0]         // 'pizza'
pedido.factura?.[0]       // undefined — factura no existe, sin error

pedido.items?.map(i => i.toUpperCase())   // ['PIZZA', 'REFRESCO']
pedido.historial?.map(i => i.fecha)       // undefined — sin error

La regla práctica: ponlo siempre en datos externos

Si el objeto viene de una API, de un formulario, de localStorage o de cualquier sitio que no controlas al 100%, usa ?. en cada tramo anidado:

// Respuesta de una API — puede llegar incompleta
const ciudad = respuesta?.usuario?.direccion?.ciudad ?? 'Sin ciudad';
//                       ^         ^           ^         ^
//                       si falta  si falta    si falta  valor por defecto

// Elemento del DOM — puede no existir en la página
const valor = document.querySelector('#campo')?.value ?? '';

La combinación ?. + ?? es muy habitual: ?. evita el error si el camino no existe, ?? da un valor por defecto si el resultado es undefined.

En la siguiente lección usamos todo esto para tomar decisiones con los condicionales.