Módulo 03: Operadores
Objetivos del módulo
- Entender qué es un operador, un operando y una expresión
- Usar los operadores aritméticos, incluidos la potencia
**y el resto% - Dominar la asignación compuesta y el incremento/decremento (prefijo frente a sufijo)
- Comparar valores correctamente:
==frente a===, yObject.is - Usar
&&,||y!sabiendo que cortocircuitan y que devuelven operandos - Distinguir
??de||y usar el encadenamiento opcional?. - Aplicar la asignación lógica
&&=,||=y??= - Escribir condiciones compactas con el operador ternario
- Conocer
typeof,instanceof,in, spread..., el operador coma y los operadores de bits - Saber en qué orden se evalúan los operadores (precedencia) y seguir buenas prácticas
1. Operadores, operandos y expresiones
📘 Concepto: Un operador es un símbolo que realiza una operación sobre uno o varios valores, llamados operandos. Una expresión es cualquier trozo de código que produce un valor. En
precio * 2, el operador es*, los operandos sonprecioy2, y toda la expresión produce un número.
Según cuántos operandos necesitan:
| Tipo | Operandos | Ejemplos |
|---|---|---|
| Unario | Uno | -x, !activo, typeof x, contador++ |
| Binario | Dos | a + b, edad >= 18, nombre ?? 'anónimo' |
| Ternario | Tres | condicion ? siSi : siNo |
const precio = 20;
const total = precio * 2 + 5; // una expresión con dos operadores
console.log(total); // 45
2. Operadores aritméticos
| Operador | Operación | Ejemplo | Resultado |
|---|---|---|---|
+ | Suma | 7 + 2 | 9 |
- | Resta | 7 - 2 | 5 |
* | Multiplicación | 7 * 2 | 14 |
/ | División | 7 / 2 | 3.5 |
% | Resto de la división | 7 % 2 | 1 |
** | Potencia (ES2016) | 2 ** 10 | 1024 |
-x | Negación (cambio de signo) | -(5) | -5 |
+x | Conversión a número | +'5' | 5 |
console.log(7 / 2); // 3.5 (la división NO es entera)
console.log(10 / 3); // 3.3333333333333335
console.log(2 ** 0.5); // 1.4142135623730951 (raíz cuadrada de 2)
2.1 El operador resto %
% devuelve lo que sobra de una división entera. Es mucho más útil de lo que parece:
console.log(17 % 5); // 2 (17 = 5 × 3 + 2)
console.log(10 % 2); // 0 → 10 es par
console.log(7 % 2); // 1 → 7 es impar
console.log(7.5 % 2); // 1.5 (también funciona con decimales)
// Usos típicos
const numero = 42;
const esPar = numero % 2 === 0; // ¿es par?
const segundosTotales = 135;
const minutos = Math.floor(segundosTotales / 60); // 2
const segundos = segundosTotales % 60; // 15
console.log(`${minutos} min ${segundos} s`); // 2 min 15 s
⚠️ Importante: En JavaScript
%es el resto, no el módulo matemático: el resultado lleva el signo del dividendo.-7 % 2da-1, no1. Por eso, para saber si un número es impar, compara con!== 0en vez de con=== 1:-7 % 2 === 1esfalse.
2.2 División entera
No hay un operador de división entera, pero puedes combinar / con Math:
console.log(Math.floor(7 / 2)); // 3 (redondea hacia abajo)
console.log(Math.trunc(7 / 2)); // 3 (quita los decimales)
console.log(Math.floor(-7 / 2)); // -4 ← con negativos son distintos
console.log(Math.trunc(-7 / 2)); // -3
2.3 La potencia ** y sus paréntesis
console.log(2 ** 3 ** 2); // 512 ← se agrupa por la DERECHA: 2 ** (3 ** 2) = 2 ** 9
console.log((-3) ** 2); // 9
console.log(-(3 ** 2)); // -9
// console.log(-3 ** 2); ❌ SyntaxError: Unary operator used immediately before exponentiation expression...
📘 Concepto: JavaScript obliga a usar paréntesis en
-3 ** 2porque en matemáticas es ambiguo (¿(-3)²o-(3²)?). Es un ejemplo de diseño que prefiere un error claro a un resultado sorprendente.
2.4 El + con textos
Como viste en el módulo 02, si uno de los operandos de + es un texto, concatena:
console.log('3' + 4 + 5); // '345'
console.log(3 + 4 + '5'); // '75' (primero 3 + 4 = 7, luego '7' + '5')
console.log('8' - '3'); // 5 (el - siempre convierte a número)
3. Asignación y operadores compuestos
El operador = asigna. Los operadores compuestos combinan una operación con la asignación:
| Operador | Equivale a | Ejemplo (si x vale 10) | x pasa a valer |
|---|---|---|---|
x += 5 | x = x + 5 | x += 5 | 15 |
x -= 3 | x = x - 3 | x -= 3 | 7 |
x *= 2 | x = x * 2 | x *= 2 | 20 |
x /= 4 | x = x / 4 | x /= 4 | 2.5 |
x %= 3 | x = x % 3 | x %= 3 | 1 |
x **= 2 | x = x ** 2 | x **= 2 | 100 |
let saldo = 100;
saldo -= 30; // pagamos 30
saldo += 50; // ingresamos 50
saldo *= 1.02; // 2 % de interés
console.log(saldo); // 122.4
let frase = 'Hola';
frase += ' mundo'; // también funciona con textos
console.log(frase); // Hola mundo
📘 Concepto: La asignación es en sí misma una expresión que devuelve el valor asignado. Por eso es posible escribir
a = b = 0(se evalúa de derecha a izquierda: primerob = 0, que devuelve0, y luegoa = 0). Úsalo con moderación: puede dificultar la lectura.
4. Incremento y decremento
++ suma 1 y -- resta 1 a una variable. Pueden ir antes (prefijo) o después (sufijo) de la variable, y la diferencia importa cuando usas el resultado en la misma expresión:
| Forma | Nombre | Qué hace | Qué devuelve |
|---|---|---|---|
x++ | Sufijo (posincremento) | Suma 1 a x | El valor anterior |
++x | Prefijo (preincremento) | Suma 1 a x | El valor nuevo |
x-- | Sufijo | Resta 1 a x | El valor anterior |
--x | Prefijo | Resta 1 a x | El valor nuevo |
let a = 5;
const b = a++; // b recibe 5 (el valor ANTES de incrementar); después a pasa a 6
console.log(a, b); // 6 5
let c = 5;
const d = ++c; // c pasa a 6 y d recibe 6 (el valor DESPUÉS de incrementar)
console.log(c, d); // 6 6
💡 Consejo: Para evitar confusiones, usa
++y--solos en su propia línea (o en elfor), donde prefijo y sufijo dan igual. Expresiones comon++ + ++nson correctas pero ilegibles. Muchos equipos prefieren directamentecontador += 1.
// ✅ Claro
let intentos = 0;
intentos++;
// ❌ Confuso
let n = 0;
const r = n++ + ++n; // ¿cuánto vale r? (respuesta: 2) Nadie debería tener que pensarlo
5. Operadores de comparación
Los operadores de comparación siempre devuelven un booleano (true o false).
5.1 Relacionales: <, >, <=, >=
console.log(10 > 5); // true
console.log(10 <= 10); // true
console.log(3 >= 7); // false
Con textos, se compara carácter a carácter según su código Unicode (orden “de diccionario” informático):
console.log('a' < 'b'); // true
console.log('abc' < 'abd'); // true
console.log('Z' < 'a'); // true ← las mayúsculas van antes que las minúsculas
console.log('á' < 'b'); // false ← las letras con tilde tienen códigos mayores
console.log('10' < '9'); // true ← ¡comparación de textos! '1' < '9'
console.log('10' < 9); // false (uno es número: convierte '10' a 10)
⚠️ Importante: Si comparas números que te llegan como texto (de un formulario, de
prompt…), conviértelos antes conNumber():'10' < '9'estrue. Y para ordenar palabras en español correctamente (tildes, eñe), usaráslocaleCompareen el módulo 08.
5.2 Igualdad: == frente a ===
| Operador | Nombre | Qué hace |
|---|---|---|
=== | Igualdad estricta | true si son del mismo tipo y tienen el mismo valor. No convierte nada |
!== | Desigualdad estricta | Lo contrario de === |
== | Igualdad débil (abstracta) | Si los tipos son distintos, convierte antes de comparar |
!= | Desigualdad débil | Lo contrario de == |
console.log(1 === 1); // true
console.log(1 === '1'); // false (number frente a string)
console.log(1 == '1'); // true (convierte '1' a 1)
El problema es que las reglas de conversión de == producen resultados difíciles de prever:
| Comparación | == | === |
|---|---|---|
1 == '1' | true | false |
0 == '' | true | false |
0 == '0' | true | false |
'' == '0' | false (¡pero los dos son == 0!) | false |
false == '0' | true | false |
false == 'false' | false | false |
null == undefined | true | false |
null == 0 | false | false |
' \t\n' == 0 | true (espacios en blanco → 0) | false |
[1, 2] == '1,2' | true | false |
[] == ![] | true (¡un valor igual a su negación!) | false |
NaN == NaN | false | false |
⚠️ Importante: Usa siempre
===y!==. Así comparas exactamente lo que ves. La única excepción que algunos equipos admiten esvalor == null, que estruetanto paranullcomo paraundefined; aun así, hoy es más claro usar??(sección 7) ovalor === null || valor === undefined.
5.3 Comparar objetos: por referencia
Dos objetos solo son iguales si son el mismo objeto, no si tienen el mismo contenido:
console.log({} === {}); // false: dos objetos distintos
console.log([1] === [1]); // false
const a = { x: 1 };
const b = a;
console.log(a === b); // true: misma referencia
5.4 Object.is: la igualdad más estricta
Object.is(a, b) es casi igual que ===, pero corrige dos casos raros:
| Comparación | === | Object.is |
|---|---|---|
NaN con NaN | false | true |
-0 con +0 | true | false |
'a' con 'a' | true | true |
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(-0, 0)); // false
En el día a día usarás ===. Object.is aparece en casos muy concretos (por ejemplo, comprobar si un valor ha cambiado en bibliotecas como React).
5.5 Comparaciones encadenadas: una trampa
console.log(1 < 2 < 3); // true (por casualidad)
console.log(3 > 2 > 1); // false ← ¿?
// Se evalúa de izquierda a derecha: (3 > 2) es true, y true > 1 → 1 > 1 → false
// ✅ Lo correcto
const x = 2;
console.log(1 < x && x < 3); // true
6. Operadores lógicos: &&, || y !
6.1 Lo básico
| Operador | Nombre | Resultado (con booleanos) |
|---|---|---|
a && b | Y lógico (AND) | true solo si ambos son true |
a \|\| b | O lógico (OR) | true si al menos uno es true |
!a | NO lógico (NOT) | Invierte: true → false y viceversa |
const edad = 25;
const tieneEntrada = true;
console.log(edad >= 18 && tieneEntrada); // true: mayor de edad Y con entrada
console.log(edad < 12 || edad > 65); // false: ni niño ni jubilado
console.log(!tieneEntrada); // false
Tablas de verdad:
a | b | a && b | a \|\| b | !a |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
6.2 Evaluación en cortocircuito
📘 Concepto:
&&y||evalúan de izquierda a derecha y se detienen en cuanto conocen el resultado. Es la evaluación en cortocircuito:
- En
a && b, siaes falsy, el resultado ya es “falso” ybni se evalúa.- En
a || b, siaes truthy, el resultado ya es “verdadero” ybni se evalúa.
const usuario = null;
// Sin cortocircuito, usuario.nombre daría error. Como usuario es null,
// la parte derecha nunca se ejecuta:
console.log(usuario && usuario.nombre); // null (sin error)
6.3 Devuelven un operando, no un booleano
Esto sorprende a quien viene de otros lenguajes: && y || no devuelven true o false, sino uno de los dos operandos:
| Expresión | Devuelve |
|---|---|
a && b | a si a es falsy; si no, b |
a \|\| b | a si a es truthy; si no, b |
console.log(true && 'hola'); // 'hola'
console.log(0 && 'hola'); // 0
console.log('Ana' || 'defecto'); // 'Ana'
console.log('' || 'defecto'); // 'defecto'
console.log(null || 0 || 'x'); // 'x' (el primer truthy, o el último si no hay ninguno)
Esto da lugar a dos patrones muy usados:
// Patrón 1: valor por defecto con ||
const nombreIntroducido = '';
const nombre = nombreIntroducido || 'Invitado';
console.log(nombre); // Invitado
// Patrón 2: ejecutar algo solo si se cumple una condición con &&
const esAdmin = true;
esAdmin && console.log('Mostrando panel de administración');
💡 Consejo: El patrón 2 es habitual en código compacto (y en JSX de React), pero en código normal un
if (esAdmin) { ... }es más legible. Úsalo con criterio.
6.4 El NO ! y la doble negación
! sí devuelve siempre un booleano. !! lo aplica dos veces y convierte cualquier valor en su booleano equivalente:
console.log(!''); // true ('' es falsy)
console.log(!'texto'); // false
console.log(!!null); // false
console.log(!!'hola'); // true
7. Nullish coalescing: ??
El problema del patrón || para valores por defecto es que trata como “vacío” cualquier valor falsy, incluidos 0, '' y false, que a menudo son valores válidos:
const volumenGuardado = 0; // el usuario ha silenciado el sonido a propósito
const volumen = volumenGuardado || 50;
console.log(volumen); // 50 ❌ ¡hemos ignorado su elección!
El operador ?? (nullish coalescing, ES2020) solo usa el valor de la derecha si el de la izquierda es null o undefined (los valores nullish):
const volumenGuardado = 0;
const volumen = volumenGuardado ?? 50;
console.log(volumen); // 0 ✅
| Expresión | \|\| | ?? |
|---|---|---|
0 ?? 10 / 0 \|\| 10 | 10 | 0 |
'' ?? 'x' / '' \|\| 'x' | 'x' | '' |
false ?? true / false \|\| true | true | false |
NaN ?? 1 / NaN \|\| 1 | 1 | NaN |
null ?? 'x' / null \|\| 'x' | 'x' | 'x' |
undefined ?? 'x' / undefined \|\| 'x' | 'x' | 'x' |
💡 Consejo: Pregúntate: “¿
0,''ofalseson valores válidos aquí?”. Si la respuesta es sí (cantidades, textos opcionales, interruptores), usa??. Si quieres sustituir cualquier valor “vacío”, usa||. En código moderno,??es casi siempre lo que buscas.
⚠️ Importante: No puedes mezclar
??con&&o||sin paréntesis:a || b ?? ces unSyntaxError. Escribe(a || b) ?? cpara dejar clara tu intención.
8. Encadenamiento opcional: ?.
Acceder a una propiedad de null o undefined es uno de los errores más frecuentes en JavaScript:
const usuario = { nombre: 'Ana', direccion: { ciudad: 'Madrid' } };
console.log(usuario.trabajo.empresa);
// ❌ TypeError: Cannot read properties of undefined (reading 'empresa')
El operador ?. (optional chaining, ES2020) comprueba si lo que hay a su izquierda es null o undefined. Si lo es, se detiene y devuelve undefined en lugar de lanzar un error:
const usuario = {
nombre: 'Ana',
direccion: { ciudad: 'Madrid' },
etiquetas: ['admin'],
saludar() {
return 'Hola';
},
};
// 1. Propiedades
console.log(usuario.direccion?.ciudad); // Madrid
console.log(usuario.trabajo?.empresa); // undefined (sin error)
// 2. Índices de arrays (y propiedades con corchetes)
console.log(usuario.etiquetas?.[0]); // admin
console.log(usuario.amigos?.[0]); // undefined
// 3. Llamadas a funciones que quizá no existan
console.log(usuario.saludar?.()); // Hola
console.log(usuario.despedir?.()); // undefined (no intenta llamar)
// Cortocircuito: si falla al principio, no evalúa el resto de la cadena
const vacio = null;
console.log(vacio?.a.b.c); // undefined
| Forma | Significa |
|---|---|
obj?.prop | obj.prop, o undefined si obj es nullish |
obj?.[clave] | obj[clave], o undefined si obj es nullish |
fn?.() | Llama a fn(), o devuelve undefined si fn es nullish |
Combinado con ?? es especialmente potente:
const ciudad = usuario.trabajo?.direccion?.ciudad ?? 'Ciudad desconocida';
console.log(ciudad); // Ciudad desconocida
⚠️ Importante: No abuses de
?.. Si una propiedad debería existir siempre, es mejor que el programa falle con un error claro a que oculte el problema con unundefinedsilencioso. Úsalo solo para lo que de verdad es opcional (datos de una API que pueden faltar, configuración opcional…). Además,?.no se puede usar a la izquierda de una asignación:usuario?.nombre = 'Luis'es un error de sintaxis.
9. Asignación lógica: &&=, ||= y ??=
ES2021 combinó los operadores lógicos con la asignación. Solo asignan si se cumple la condición correspondiente:
| Operador | Equivale a | Asigna cuando x es… |
|---|---|---|
x \|\|= y | x \|\| (x = y) | falsy |
x &&= y | x && (x = y) | truthy |
x ??= y | x ?? (x = y) | null o undefined |
const config = { tema: '', volumen: 0, idioma: null };
config.tema ||= 'claro'; // '' es falsy → asigna
config.volumen ??= 50; // 0 no es nullish → NO asigna
config.idioma ??= 'es'; // null es nullish → asigna
console.log(config); // { tema: 'claro', volumen: 0, idioma: 'es' }
const sesion = { usuario: 'ana' };
sesion.usuario &&= sesion.usuario.toUpperCase(); // solo si hay usuario
console.log(sesion); // { usuario: 'ANA' }
💡 Consejo:
??=es ideal para valores por defecto de opciones: “si no me has dicho nada, uso esto”. Fíjate en que, a diferencia dex = x ?? y, sixya tiene valor no se realiza ninguna asignación.
10. El operador ternario ? :
Es el único operador con tres operandos. Elige entre dos valores según una condición:
condición ? valorSiVerdadero : valorSiFalso
const edad = 20;
const tipo = edad >= 18 ? 'mayor de edad' : 'menor de edad';
console.log(tipo); // mayor de edad
const stock = 0;
console.log(`Producto ${stock > 0 ? 'disponible' : 'agotado'}`); // Producto agotado
const unidades = 1;
console.log(`${unidades} ${unidades === 1 ? 'unidad' : 'unidades'}`); // 1 unidad
💡 Consejo: El ternario es perfecto para elegir un valor (dentro de una plantilla, al inicializar una
const). Para ejecutar acciones distintas, o si necesitas anidar varios ternarios, usaif/else(módulo 04):a ? b : c ? d : ees difícil de leer.
11. Otros operadores
11.1 typeof
Ya lo conoces del módulo 02: devuelve el tipo de un valor como texto.
console.log(typeof 42); // number
console.log(typeof 'hola'); // string
console.log(typeof undefined); // undefined
11.2 instanceof (adelanto)
Comprueba si un objeto fue creado a partir de una clase o constructor concreto. Lo entenderás del todo en el módulo 09:
console.log([] instanceof Array); // true
console.log(new Date() instanceof Date); // true
console.log([] instanceof Object); // true (los arrays también son objetos)
11.3 in (adelanto)
Comprueba si una propiedad existe en un objeto:
const usuario = { nombre: 'Ana' };
console.log('nombre' in usuario); // true
console.log('edad' in usuario); // false
console.log(0 in ['x']); // true (el índice 0 existe)
11.4 Spread ... (adelanto)
Los tres puntos “esparcen” los elementos de un array, una cadena o las propiedades de un objeto. Lo verás a fondo en los módulos 06 y 07:
const numeros = [3, 7, 1];
console.log(Math.max(...numeros)); // 7 (equivale a Math.max(3, 7, 1))
console.log([...numeros, 10]); // [ 3, 7, 1, 10 ]
console.log([...'hola']); // [ 'h', 'o', 'l', 'a' ]
const direccion = { ciudad: 'Madrid' };
console.log({ ...direccion, cp: 28001 }); // { ciudad: 'Madrid', cp: 28001 }
11.5 El operador coma (mención)
Evalúa varias expresiones de izquierda a derecha y devuelve la última. Casi solo se ve en bucles for con dos variables o en código minificado:
const k = (1, 2, 3);
console.log(k); // 3
for (let i = 0, j = 10; i < j; i++, j--) {
// i sube y j baja a la vez
}
⚠️ Importante: No uses el operador coma en tu código salvo en el
for. Su presencia suele indicar un error: por ejemplo,Math.max(1, 2)no es el operador coma (son argumentos), peroconst x = (a, b)sí lo es, y probablemente no es lo que querías.
12. Operadores de bits (breve)
Trabajan con los números a nivel de bits (ceros y unos), convirtiéndolos temporalmente a enteros de 32 bits. Son poco frecuentes en aplicaciones web, pero aparecen en gráficos, criptografía, compresión o permisos.
| Operador | Nombre | Ejemplo | Resultado |
|---|---|---|---|
& | AND de bits | 5 & 3 (101 & 011) | 1 (001) |
\| | OR de bits | 5 \| 3 | 7 (111) |
^ | XOR de bits | 5 ^ 3 | 6 (110) |
~ | NOT de bits | ~5 | -6 |
<< | Desplazamiento a la izquierda | 5 << 1 | 10 |
>> | Desplazamiento a la derecha | 5 >> 1 | 2 |
>>> | Desplazamiento a la derecha sin signo | -5 >>> 28 | 15 |
// Ejemplo práctico: permisos combinados como "banderas"
const LEER = 0b001; // 1
const ESCRIBIR = 0b010; // 2
const BORRAR = 0b100; // 4
const permisos = LEER | ESCRIBIR; // 3 (0b011)
console.log((permisos & ESCRIBIR) !== 0); // true: puede escribir
console.log((permisos & BORRAR) !== 0); // false: no puede borrar
⚠️ Importante: No confundas
&con&&ni|con||.if (a & b)es una operación de bits, no un “y lógico”. Es un error de tecleo frecuente que ESLint puede detectar.
13. Precedencia de operadores
📘 Concepto: La precedencia decide qué operador se aplica primero cuando hay varios en una expresión, igual que en matemáticas la multiplicación va antes que la suma. La asociatividad decide el orden cuando tienen la misma precedencia (de izquierda a derecha o al revés).
console.log(2 + 3 * 4); // 14 (primero 3 * 4)
console.log((2 + 3) * 4); // 20 (los paréntesis mandan)
Tabla simplificada, de mayor a menor precedencia:
| Nivel | Operadores | Asociatividad |
|---|---|---|
| 1 | ( ... ) agrupación | — |
| 2 | ., ?., [], llamadas f(), new | Izquierda a derecha |
| 3 | Sufijos x++, x-- | — |
| 4 | Unarios: !, -x, +x, ++x, --x, typeof, await | Derecha a izquierda |
| 5 | ** | Derecha a izquierda |
| 6 | *, /, % | Izquierda a derecha |
| 7 | +, - | Izquierda a derecha |
| 8 | <<, >>, >>> | Izquierda a derecha |
| 9 | <, <=, >, >=, in, instanceof | Izquierda a derecha |
| 10 | ==, !=, ===, !== | Izquierda a derecha |
| 11 | &, después ^, después \| | Izquierda a derecha |
| 12 | && | Izquierda a derecha |
| 13 | \|\|, ?? | Izquierda a derecha |
| 14 | ? :, =, +=, &&=, \|\|=, ??=, =>… | Derecha a izquierda |
| 15 | , | Izquierda a derecha |
// Cómo se lee una expresión con varios operadores
const edad = 30;
const tieneCarne = true;
const resultado = edad >= 18 && tieneCarne || edad > 70;
// 1º comparaciones: (edad >= 18) → true, (edad > 70) → false
// 2º &&: true && true → true
// 3º ||: true || false → true
console.log(resultado); // true
💡 Consejo: Nadie se sabe la tabla entera de memoria. Lo profesional es usar paréntesis siempre que la expresión no sea obvia:
(edad >= 18 && tieneCarne) || edad > 70se entiende a la primera.
14. Buenas prácticas y errores comunes
| ❌ Evita | ✅ Prefiere | Por qué |
|---|---|---|
if (x == 0) | if (x === 0) | == convierte tipos ('' == 0 es true) |
if (x === NaN) | if (Number.isNaN(x)) | NaN nunca es igual a nada |
const v = cantidad \|\| 1 (si 0 es válido) | const v = cantidad ?? 1 | \|\| descarta 0, '' y false |
a && b && a.b && a.b.c | a?.b?.c | Más corto y legible |
x = x + 1 | x += 1 o x++ | Más conciso |
const r = n++ + ++n | Varias líneas simples | Ilegible y propenso a errores |
if (1 < x < 10) | if (1 < x && x < 10) | La primera siempre es true |
a ? b : c ? d : e | if / else if / else | Los ternarios anidados se leen mal |
'10' < '9' con datos de formulario | Number(a) < Number(b) | Los textos se comparan carácter a carácter |
if (a = 5) | if (a === 5) | = asigna; es un error clásico de tecleo |
⚠️ Importante:
if (a = 5)no da error: asigna 5 aay, como 5 es truthy, siempre entra en elif. Es un fallo muy difícil de ver. ESLint lo detecta con la reglano-cond-assign.
15. Ejercicios
Ejercicio 1: Calculadora de operaciones
Declara dos constantes a = 17 y b = 5 y muestra en una tabla (console.table con un objeto) el resultado de +, -, *, /, %, **, la división entera con Math.trunc y si a es par. Repite con a = -17 y explica por qué cambia el resto.
Ejercicio 2: Conversor de tiempo
Dada una cantidad de segundos (por ejemplo, 98765), calcula cuántos días, horas, minutos y segundos son usando /, Math.floor y %. Muestra el resultado como 1 d 3 h 26 min 5 s.
Ejercicio 3: Predice el resultado
Sin ejecutar, escribe el resultado de cada expresión. Después compruébalo y explica los fallos:
'5' + 3 - 1
'5' - 3 + 1
0 == '0'
0 === '0'
null ?? 'a'
0 || 'b'
0 ?? 'c'
'' && 'd'
'e' && 'f'
!!'0'
3 > 2 > 1
2 ** 3 ** 2
Ejercicio 4: Precio con descuentos
Escribe un programa con las constantes precio, esSocio (booleano), cupon (texto que puede ser '') y unidades. Calcula:
- Descuento del 10 % si
esSocio(usa el ternario). - 5 € menos si
cuponno está vacío (usa&&o el ternario). - Envío gratis si el total supera 50 € o el cliente es socio. Muestra un resumen con plantillas de texto y prueba varias combinaciones.
Ejercicio 5: Configuración por defecto
Dado el objeto const preferencias = { tema: null, fuente: 0, notificaciones: false, idioma: '' };, usa ??= y ||= para que, al final, tema sea 'oscuro', fuente siga siendo 0, notificaciones siga siendo false e idioma sea 'es'. Justifica en un comentario qué operador has elegido para cada propiedad.
Ejercicio 6: Datos opcionales de una API
Tienes esta respuesta de una API:
const respuesta = {
pedido: { id: 1042, cliente: { nombre: 'Luis' }, lineas: [{ producto: 'Ratón', precio: 19.9 }] },
};
Usando ?. y ??, muestra: el nombre del cliente, su email (o 'sin email'), el nombre del primer producto, el precio del segundo producto (o 0) y el resultado de llamar a respuesta.pedido.calcularTotal si existe (o 'no disponible'). Ninguna línea debe lanzar error.
Ejercicio 7: Permisos con bits
Define las banderas LEER = 1, ESCRIBIR = 2, BORRAR = 4 y ADMIN = 8. Crea tres usuarios con distintas combinaciones de permisos usando | y escribe, para cada uno, si puede leer, escribir, borrar o es administrador usando &. ¿Qué número resulta de combinar todos los permisos?
Resumen
| Concepto | Sintaxis | Nota |
|---|---|---|
| Aritméticos | + - * / % ** | % es el resto (signo del dividendo) |
| Asignación compuesta | += -= *= /= %= **= | x += 1 equivale a x = x + 1 |
| Incremento | x++ / ++x | Sufijo devuelve el valor anterior; prefijo, el nuevo |
| Igualdad estricta | ===, !== | Úsala siempre |
| Igualdad débil | ==, != | Convierte tipos: evítala |
| Igualdad exacta | Object.is(a, b) | NaN igual a NaN; -0 distinto de 0 |
| Lógicos | &&, \|\|, ! | Cortocircuitan y devuelven un operando |
| Nullish coalescing | a ?? b | b solo si a es null o undefined |
| Encadenamiento opcional | a?.b, a?.[i], f?.() | undefined en vez de error |
| Asignación lógica | \|\|=, &&=, ??= | Asignan solo si se cumple la condición |
| Ternario | cond ? a : b | Para elegir valores, no para anidar |
| Tipo y pertenencia | typeof, instanceof, in | Tipo, clase y existencia de propiedad |
| Spread | ...array, ...objeto | Esparce elementos o propiedades |
| Bits | & \| ^ ~ << >> >>> | Enteros de 32 bits; no confundir con && |
| Precedencia | ( ) primero | Ante la duda, paréntesis |