---
title: "Operadores en JavaScript: la guía completa"
excerpt: "Todos los operadores de JavaScript en un sitio: asignación, incremento y decremento, lógicos, matemáticos y el resto. AND y OR no devuelven true o false, devuelven uno de los operandos, y de ahí sale el cortocircuito, los valores por defecto y por qué a veces conviene ?? en lugar de ||."
date: "2019-07-15T00:10:27.000Z"
lastModified: "2026-09-08T11:00:00.000Z"
category: "JavaScript"
tech_article: true
seo_title: "Operadores en JavaScript: asignación, lógicos, matemáticos y resto"
seo_description: "Guía completa de los operadores de JavaScript: asignación, ++ prefijo y sufijo, negación, && y || (que devuelven un operando, no un booleano), cortocircuito, ?? frente a ||, el operador resto % y la asignación compuesta."
author:
  name: "angel cruz"
  picture: "/images/me/angel-cruz.png"
---

**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`.

```js
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.

```js
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.**

```js
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:

```js
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.

```js
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**.

```js
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:

```js
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:

```js
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**.

```js
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:

```js
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:

```js
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`:

```js
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 (`/`).

```js
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.

```js
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.

```js
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:

```js
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:

```js
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:

```js
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

- [El operador ternario en PHP](/post/el-operador-ternario-php), el mismo concepto en otro lenguaje
- [Igual (==) frente a idéntico (===) en PHP](/post/igual-vs-identico-php)
- [TypeScript 7 y el fin de la API en JavaScript](/post/typescript-7-sin-api-javascript-eslint), si de JavaScript ya has pasado a TypeScript
- Dos sitios donde este mismo JavaScript aparece donde no lo esperas: [Alpine.js](/post/hablemos-sobre-alpinejs) para interactividad sin framework, y un [Arduino Uno programado con JavaScript](/post/arduino-uno-con-javascript)

## Fuentes

- [Logical AND (&&)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND), MDN
- [Nullish coalescing operator (??)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing), MDN
- [Remainder (%)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder), MDN
- [Increment (++)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Increment), MDN

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/operadores-en-javascript](https://www.angelcruz.dev/post/operadores-en-javascript)
