Operadores y expresiones
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/elsepara 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 esundefined.
En la siguiente lección usamos todo esto para tomar decisiones con los condicionales.