JavaScript

Operadores en JavaScript: la guía completa

Autorangel cruz
Actualizado
Publicado
Lectura6 min de lectura

En JavaScript, && y || no devuelven true o false: devuelven uno de los dos operandos. Es lo primero que hay que entender, porque casi todo lo demás (el cortocircuito, los valores por defecto, el patrón de renderizado condicional) sale de ahí.

Si vienes de otro lenguaje esto sorprende. 1 && 2 no vale true, vale 2.

Antes de llegar ahí, los que se usan a diario y casi nunca se explican del todo.

Operadores de asignación

El operador de asignación es el más usado y el más sencillo: guarda un valor en una variable declarada con let o const.

let mensaje = "hola";
const PI = 3.1416;

La diferencia entre los dos importa para lo que viene: const no permite reasignar, así que cualquier operador que cambie el valor de la variable necesita let.

Incremento y decremento

Solo son válidos para variables numéricas y suman o restan una unidad.

let numero = 6;
++numero;
console.log(numero); // 7
 
let otro = 6;
--otro;
console.log(otro);   // 5

La diferencia entre ++i e i++

Aquí está el detalle que se pregunta en cada entrevista. Si ++ va como prefijo, el valor se incrementa antes de usarlo en la expresión. Si va como sufijo, se incrementa después.

let numero1 = 5;
const numero2 = 2;
const resultadoSufijo = numero1++ + numero2; // 7, y numero1 queda en 6
 
let numero3 = 5;
const resultadoPrefijo = ++numero3 + numero2; // 8, y numero3 queda en 6

En los dos casos la variable acaba valiendo 6. Lo que cambia es el valor con el que se hizo la suma.

Negación lógica

Se obtiene con ! como prefijo y devuelve el valor contrario:

const visible = true;
console.log(!visible); // false

Con valores que no son booleanos, JavaScript los convierte primero:

  • Un número se convierte en false si vale 0, y en true con cualquier otro valor (positivo o negativo, decimal o entero).
  • Una cadena se convierte en false si está vacía (""), y en true en cualquier otro caso.
let cantidad = 0;
let vacio = !cantidad;   // true
cantidad = 2;
vacio = !cantidad;       // false
 
let mensaje = "";
let mensajeVacio = !mensaje;  // true
mensaje = "Bienvenido";
mensajeVacio = !mensaje;      // false

Esa tabla de conversiones es la misma que gobierna && y ||, que es lo siguiente.

Operador lógico AND (&&)

&& evalúa de izquierda a derecha y devuelve el primer operando falsy que encuentre; si todos son truthy, devuelve el último.

const a = true && true;      // true
const b = true && false;     // false
const c = "Gato" && "Perro"; // "Perro"  ← el último, porque los dos son truthy
const d = 2 && 0;            // 0        ← el primer falsy
const e = "" && "algo";      // ""       ← el primer falsy

Cuando los dos operandos son booleanos se comporta como esperarías, y por eso el error pasa desapercibido durante años. En cuanto metes números o cadenas, la diferencia aparece.

Cortocircuito

&& deja de evaluar en cuanto encuentra algo falsy. El resto ni se ejecuta:

function a() {
  console.log("se llamó a a");
  return false;
}
function b() {
  console.log("se llamó a b");
  return true;
}
 
console.log(a() && b());
// se llamó a a
// false

b() nunca se llama. Esto no es una optimización interna: es comportamiento garantizado, y es la razón de que este patrón funcione:

usuario && usuario.nombre;   // no revienta si usuario es null

Aunque hoy para eso conviene más el encadenamiento opcional, usuario?.nombre.

Operador OR (||)

La imagen especular: || devuelve el primer operando truthy; si todos son falsy, devuelve el último.

const a = false || true;   // true
const b = false || false;  // false
const c = "Gato" || "Perro"; // "Gato" ← el primero, ya es truthy
const d = 0 || "vacío";      // "vacío"

De aquí sale el patrón clásico del valor por defecto:

const nombre = entrada || "anónimo";

El problema de || como valor por defecto

|| se dispara con cualquier valor falsy, y eso incluye 0, "" y false, que muchas veces son valores legítimos:

const cantidad = 0;
const texto = "";
 
const total = cantidad || 42;      // 42, y no 0
const mensaje = texto || "¡hola!"; // "¡hola!", y no ""

Si 0 era una cantidad real, acabas de perderla.

Para eso está ??, el operador de coalescencia nula, que solo cae al lado derecho si el izquierdo es null o undefined:

const cantidad = 0;
const texto = "";
 
const total = cantidad ?? 42;      // 0   ← se respeta
const mensaje = texto ?? "¡hola!"; // ""  ← se respeta

Regla práctica: si 0, "" o false son valores válidos en tu caso, usa ??. Si lo que quieres es descartar cualquier cosa vacía, || está bien.

Operadores matemáticos

Los cuatro de siempre: suma (+), resta (-), multiplicación (*) y división (/).

const numero1 = 10;
const numero2 = 5;
 
numero1 / numero2; // 2
3 + numero1;       // 13
numero2 - 4;       // 1
numero1 * numero2; // 50

El operador % es el resto, no el módulo

Se le llama «módulo» por costumbre y no lo es. En JavaScript % es el operador resto, y la diferencia se ve con números negativos: el resultado toma siempre el signo del dividendo, o sea del operando de la izquierda.

13 % 5;  //  3
-13 % 5; // -3   ← negativo, porque el dividendo lo es
4 % 2;   //  0
-4 % 2;  // -0
1 % -2;  //  1   ← positivo, el signo del divisor da igual

En Python o Perl, donde % sí es módulo, -13 % 5 da 2. Si estás traduciendo un algoritmo de otro lenguaje, este es el detalle que te va a costar una tarde.

Con números positivos, que es el 90% de los casos, se comporta como esperas: calcula el resto de la división entera.

10 % 5; // 0, la división es exacta
9 % 5;  // 4, sobra 4

De ahí el uso más común, saber si un número es par:

const esPar = (n) => n % 2 === 0;

Asignación compuesta

Cualquier operador matemático se combina con = para abreviar. Ojo con esto, porque cada línea opera sobre el resultado de la anterior, no sobre el valor inicial:

let numero = 5;
 
numero += 3; // numero = 5 + 3  → 8
numero -= 1; // numero = 8 - 1  → 7
numero *= 2; // numero = 7 * 2  → 14
numero /= 5; // numero = 14 / 5 → 2.8
numero %= 4; // numero = 2.8 % 4 → 2.8

Se usa let y no const porque el valor cambia. Con const la primera reasignación lanza TypeError.

Asignación lógica

Los tres operadores lógicos también tienen su versión de asignación:

let a = null;
a ??= "por defecto"; // solo asigna si a es null o undefined
 
let b = 0;
b ||= 10;  // asigna 10, porque 0 es falsy
 
let c = 1;
c &&= 5;   // asigna 5, porque 1 es truthy

??= es el que más se usa, y por lo mismo que ??: es el único que no pisa un 0 legítimo.

Preguntas frecuentes

¿Qué devuelve && en JavaScript?

Uno de los operandos, no un booleano. Devuelve el primer valor falsy que encuentra evaluando de izquierda a derecha, o el último operando si todos son truthy. Por eso "Gato" && "Perro" devuelve "Perro".

¿Cuál es la diferencia entre || y ??

|| cae al lado derecho con cualquier valor falsy, incluidos 0, "" y false. ?? solo lo hace con null y undefined. Si 0 es un valor válido en tu caso, || te lo va a machacar y ?? no.

¿Cuál es la diferencia entre ++i e i++?

Las dos incrementan la variable en uno. La diferencia es cuándo: como prefijo (++i) el valor se incrementa antes de usarse en la expresión, y como sufijo (i++) después. Si el operador está solo en su línea, da exactamente igual cuál uses.

¿% es el operador módulo en JavaScript?

No, es el operador resto. La diferencia solo se nota con negativos: el resto toma el signo del dividendo, así que -13 % 5 da -3 en JavaScript y 2 en Python.

¿Qué es el cortocircuito?

Que el operador deja de evaluar en cuanto sabe el resultado. false && f() nunca llama a f(), y true || f() tampoco. Es comportamiento garantizado, así que se puede usar para proteger un acceso.

¿Cómo saber si un número es par?

Con el resto: n % 2 === 0. Funciona también con negativos, porque -4 % 2 da -0 y -0 === 0 es true.

¿Por qué mi variable no cambia con +=?

Probablemente la declaraste con const. La asignación compuesta reasigna la variable, así que necesita let.

Enlaces de interés

Fuentes

¿Tienes un proyecto en mente?

Trabajo con Laravel, WordPress, SEO técnico y servidores MCP. El primer paso es una llamada de descubrimiento, sin costo ni compromiso, donde me cuentas qué necesitas y te digo con honestidad si puedo ayudarte.

Hablemos