En la lección anterior aprendiste a guardar los datos de una tarea de Taller Nómada en variables del tipo adecuado. Guardar está bien, pero un programa que no calcula nada sirve de poco. Los operadores son los símbolos que combinan y transforman valores: sumar horas, calcular porcentajes, decidir si una condición se cumple o proporcionar un valor por defecto cuando falta un dato. En esta lección los recorrerás todos —desde el humilde + hasta los modernos ?? y ?.— y acabarás calculando la carga de trabajo real de Marta, Iván y Lucía.
Contenido
- Operadores aritméticos
- Incremento y decremento: prefijo y sufijo
- Operadores de asignación
- Operadores lógicos y cortocircuito
- Coalescencia nula:
??y??= - Encadenamiento opcional:
?. - El operador ternario
? : - Concatenación frente a template literals
- Precedencia de operadores
- Aplicación: la carga de horas del equipo
- Errores Comunes y Consejos
- Ejercicios
- Conclusión
- Operadores aritméticos
Son los que hacen cálculos numéricos.
| Operador | Nombre | Ejemplo | Resultado |
|---|---|---|---|
+ |
Suma | 12 + 8 |
20 |
- |
Resta | 12 - 8 |
4 |
* |
Multiplicación | 12 * 2 |
24 |
/ |
División | 12 / 8 |
1.5 |
% |
Módulo (resto) | 12 % 8 |
4 |
** |
Exponenciación | 2 ** 3 |
8 |
const horasIvan = 12;
const horasLucia = 8;
console.log(horasIvan + horasLucia); // 20
console.log(horasIvan - horasLucia); // 4
console.log(horasIvan / horasLucia); // 1.5
console.log(horasIvan % horasLucia); // 41.1 El módulo % es más útil de lo que parece
% devuelve el resto de una división entera. Sus dos usos clásicos:
Saber si un número es par o impar:
const numeroTarea = 7;
console.log(numeroTarea % 2); // 1 → impar
console.log(numeroTarea % 2 === 0); // falseRepartir en ciclos. En Nómada Tareas lo usaremos para asignar tareas rotando entre las tres personas del equipo:
// El equipo tiene 3 personas: posiciones 0, 1 y 2
console.log(0 % 3); // 0 → Marta
console.log(1 % 3); // 1 → Iván
console.log(2 % 3); // 2 → Lucía
console.log(3 % 3); // 0 → Marta otra vez
console.log(4 % 3); // 1 → IvánEl resto de dividir entre 3 siempre da 0, 1 o 2: exactamente las posiciones del equipo, cíclicamente.
1.2 La división nunca falla
En muchos lenguajes dividir entre cero provoca un error. En JavaScript, no:
Esto es peligroso porque el programa no se detiene: sigue calculando con Infinity o NaN y el error aparece mucho más tarde, en un sitio que no tiene nada que ver.
const tareasCompletadas = 5;
const tareasTotales = 0; // ¡todavía no hay tareas!
const porcentaje = (tareasCompletadas / tareasTotales) * 100;
console.log(porcentaje); // Infinity — no es un error, pero está malLa solución es comprobar el divisor antes de dividir, algo que harás cómodamente cuando aprendas condicionales en el Módulo 2.
1.3 El + tiene doble personalidad
Aquí llega la primera gran trampa. + es a la vez suma y concatenación de textos:
console.log(12 + 8); // 20 → suma numérica
console.log('12' + '8'); // '128' → concatenación de textos
console.log('12' + 8); // '128' → ¡si uno es texto, concatena!
console.log(12 + '8'); // '128'La regla es implacable: si alguno de los dos operandos es un string, + concatena. Este comportamiento es la causa número uno de los cálculos incorrectos en principiantes, sobre todo con datos que vienen de un formulario (donde todo llega como texto).
El resto de operadores aritméticos no tienen este problema: intentan convertir a número.
console.log('12' - 8); // 4 → convierte '12' a número
console.log('12' * 2); // 24
console.log('12' / 2); // 6
console.log('alta' * 2); // NaN → no se puede convertirEn Conversión de Tipos y Comparaciones verás exactamente por qué ocurre esto y cómo protegerte.
- Incremento y decremento: prefijo y sufijo
++ suma 1 y -- resta 1 a una variable.
let tareasCompletadas = 5;
tareasCompletadas++;
console.log(tareasCompletadas); // 6
tareasCompletadas--;
console.log(tareasCompletadas); // 5Ambos tienen dos formas, y la diferencia importa solo cuando usas el resultado en la misma expresión:
| Forma | Nombre | Qué hace |
|---|---|---|
x++ |
Sufija (postfija) | Devuelve el valor antiguo y luego incrementa |
++x |
Prefija | Incrementa y luego devuelve el valor nuevo |
let a = 5;
console.log(a++); // 5 ← devuelve el valor antiguo
console.log(a); // 6 ← pero ya está incrementada
let b = 5;
console.log(++b); // 6 ← incrementa primero
console.log(b); // 6Mnemotecnia: el ++ se ejecuta en la posición en la que está escrito. Si va delante, primero incrementa; si va detrás, primero devuelve.
Consejo práctico: usa ++ y -- en líneas sueltas, nunca dentro de expresiones complejas. Este tipo de código es una fuente inagotable de errores:
- Operadores de asignación
= asigna un valor. Los demás combinan una operación con la asignación:
| Operador | Equivale a | Ejemplo | Resultado (partiendo de h = 12) |
|---|---|---|---|
= |
— | h = 8 |
8 |
+= |
h = h + 8 |
h += 8 |
20 |
-= |
h = h - 8 |
h -= 8 |
4 |
*= |
h = h * 2 |
h *= 2 |
24 |
/= |
h = h / 4 |
h /= 4 |
3 |
%= |
h = h % 5 |
h %= 5 |
2 |
**= |
h = h ** 2 |
h **= 2 |
144 |
let horasAcumuladas = 0;
horasAcumuladas += 12; // tarea de Iván
horasAcumuladas += 8; // tarea de Lucía
horasAcumuladas += 6; // tarea de Marta
console.log(horasAcumuladas); // 26+= también funciona con textos, y por la misma razón que +:
let resumen = 'Equipo: ';
resumen += 'Marta, ';
resumen += 'Iván, ';
resumen += 'Lucía';
console.log(resumen); // Equipo: Marta, Iván, LucíaRecuerda que las variables asignadas con estos operadores deben declararse con let: con const obtendrías un TypeError.
- Operadores lógicos y cortocircuito
Son tres, y esconden un comportamiento que conviene entender bien.
| Operador | Nombre | Significado informal |
|---|---|---|
&& |
Y lógico (AND) | Ambos deben cumplirse |
|| |
O lógico (OR) | Basta con que uno se cumpla |
! |
Negación (NOT) | Invierte el valor lógico |
const esUrgente = true;
const estaAsignada = false;
console.log(esUrgente && estaAsignada); // false
console.log(esUrgente || estaAsignada); // true
console.log(!esUrgente); // false4.1 La evaluación de cortocircuito
JavaScript evalúa estos operadores de izquierda a derecha y se detiene en cuanto conoce el resultado:
- Con
&&: si el primer valor es falso, el resultado ya es falso. No evalúa el segundo. - Con
||: si el primer valor es verdadero, el resultado ya es verdadero. No evalúa el segundo.
function avisar() {
console.log('Aviso enviado a Marta');
return true;
}
false && avisar(); // No imprime nada: se detiene en el false
true || avisar(); // No imprime nada: se detiene en el true
true && avisar(); // Imprime 'Aviso enviado a Marta'Esto se usa muchísimo como atajo para "haz esto solo si aquello se cumple":
4.2 Lo que devuelven realmente
Aquí está el detalle que casi nadie explica: && y || no devuelven true o false. Devuelven uno de los operandos.
a || bdevuelveasiaes truthy; si no, devuelveb.a && bdevuelveasiaes falsy; si no, devuelveb.
console.log('Iván' || 'sin asignar'); // 'Iván'
console.log('' || 'sin asignar'); // 'sin asignar'
console.log(0 || 40); // 40
console.log('alta' && 'media'); // 'media'
console.log(null && 'media'); // null(Los conceptos truthy y falsy —qué valores se consideran verdaderos o falsos sin serlo— se detallan en la próxima lección. Por ahora basta saber que 0, '', null, undefined y NaN son falsy, y prácticamente todo lo demás es truthy.)
Este comportamiento habilita el patrón clásico del valor por defecto:
const responsableRecibido = '';
const responsable = responsableRecibido || 'Sin asignar';
console.log(responsable); // 'Sin asignar'Pero cuidado: tiene una trampa importante.
const horasRecibidas = 0; // ¡0 es un valor legítimo!
const horas = horasRecibidas || 8;
console.log(horas); // 8 ← ¡mal! Queríamos 0Como 0 es falsy, || lo descarta. Para resolver esto exactamente se creó ??.
4.3 El operador ! y el doble !!
! invierte el valor lógico:
Aplicado dos veces, !! convierte cualquier valor a su equivalente booleano:
console.log(!!'Iván'); // true
console.log(!!''); // false
console.log(!!0); // false
console.log(!!12); // true
console.log(!!null); // falseEs un truco muy extendido, aunque Boolean(valor) expresa lo mismo con más claridad.
- Coalescencia nula:
?? y ??=
?? y ??=El operador ?? (ES2020) devuelve el operando derecho solo si el izquierdo es null o undefined. A diferencia de ||, respeta el 0, el '' y el false.
const horasRecibidas = 0;
console.log(horasRecibidas || 8); // 8 ← || descarta el 0
console.log(horasRecibidas ?? 8); // 0 ← ?? lo respetaComparativa completa:
| Valor izquierdo | valor || 'defecto' |
valor ?? 'defecto' |
|---|---|---|
'Iván' |
'Iván' |
'Iván' |
'' |
'defecto' |
'' |
0 |
'defecto' |
0 |
false |
'defecto' |
false |
NaN |
'defecto' |
NaN |
null |
'defecto' |
'defecto' |
undefined |
'defecto' |
'defecto' |
Regla práctica: para valores por defecto, usa ??. Usa || solo cuando quieras tratar también el 0 y la cadena vacía como "ausencia de valor" a propósito.
flowchart TD
A["Necesitas un<br/>valor por defecto"] --> B{"¿El 0, el false<br/>y la cadena vacía<br/>son datos válidos?"}
B -->|"Sí (horas, contadores)"| C["Usa ??<br/>solo actúa ante<br/>null y undefined"]
B -->|"No (nombres, textos)"| D["Puedes usar ||<br/>actúa ante cualquier<br/>valor falsy"]
C --> E["horasEstimadas ?? 8"]
D --> F["responsable || 'Sin asignar'"]
const responsable = null;
const horasEstimadas = 0;
console.log(responsable ?? 'Sin asignar'); // 'Sin asignar'
console.log(horasEstimadas ?? 8); // 0 — correcto5.1 Asignación con ??=
??= asigna un valor solo si la variable es null o undefined:
let revisor = null;
revisor ??= 'Marta';
console.log(revisor); // 'Marta'
let responsable = 'Lucía';
responsable ??= 'Marta';
console.log(responsable); // 'Lucía' — no se tocaEquivale a if (revisor === null || revisor === undefined) { revisor = 'Marta'; }, pero en una línea.
Existen también ||= y &&= con la misma lógica aplicada a truthy/falsy.
5.2 Una restricción de sintaxis
No puedes mezclar ?? con && o || sin paréntesis: es un SyntaxError deliberado, para evitar ambigüedades.
// const x = a || b ?? c; // SyntaxError
const x = (a || b) ?? c; // Correcto: los paréntesis aclaran la intención
- Encadenamiento opcional:
?.
?.El operador ?. (ES2020) accede a una propiedad solo si el valor anterior no es null ni undefined. Si lo es, devuelve undefined en lugar de lanzar un error.
El problema que resuelve:
const tarea = { titulo: 'Rediseñar la sala', responsable: null };
// console.log(tarea.responsable.length); // TypeError: Cannot read properties of nullEse TypeError detiene el programa entero. Con ?.:
Se puede encadenar tantas veces como haga falta:
const tarea = { titulo: 'Montar la exposición' };
console.log(tarea.revision?.autor); // undefined
console.log(tarea.revision?.autor?.nombre); // undefinedSin ?., la segunda línea lanzaría un TypeError en cuanto tarea.revision fuese undefined.
Se combina de maravilla con ??:
const tarea = { titulo: 'Revisar facturas', responsable: null };
const nombre = tarea.responsable?.nombre ?? 'Sin asignar';
console.log(nombre); // 'Sin asignar'Aviso importante: ?. no es una excusa para no comprobar los datos. Si lo pones en todas partes, ocultarás errores reales en lugar de resolverlos. Úsalo donde de verdad sea legítimo que el valor falte.
El uso completo de
?.con objetos anidados, arrays (tarea?.etiquetas?.[0]) y llamadas a funciones (tarea.guardar?.()) se retomará en el Módulo 4, cuando trabajes con objetos de verdad.
- El operador ternario
? :
? :Es el único operador de JavaScript que toma tres operandos. Su forma:
const horasEstimadas = 12;
const tipoTarea = horasEstimadas > 8 ? 'larga' : 'corta';
console.log(tipoTarea); // 'larga'Se lee como una pregunta: ¿horasEstimadas > 8? Entonces 'larga'; si no, 'corta'.
La gran ventaja frente a un if es que el ternario es una expresión: produce un valor y por tanto puede asignarse, pasarse como argumento o interpolarse.
const responsable = 'Marta';
const horas = 6;
console.log(`${responsable} tiene una tarea ${horas > 8 ? 'larga' : 'corta'}`);
// Marta tiene una tarea cortaSe pueden encadenar, aunque conviene no abusar:
const horasEstimadas = 12;
const categoria =
horasEstimadas > 16 ? 'proyecto' :
horasEstimadas > 8 ? 'larga' :
horasEstimadas > 2 ? 'media' :
'rápida';
console.log(categoria); // 'larga'Alineado así se lee bien, pero a partir de tres o cuatro casos es mejor un switch o un if/else, que verás en el Módulo 2.
Cuándo usar cada uno:
| Situación | Herramienta |
|---|---|
| Elegir entre dos valores para asignarlos | Ternario |
| Insertar una decisión dentro de un texto | Ternario |
| Ejecutar varias sentencias según la condición | if/else |
| Muchos casos sobre el mismo valor | switch |
- Concatenación frente a template literals
Ya conoces las dos formas de componer texto. Comparémoslas de frente:
const responsable = 'Iván';
const horas = 12;
const fechaLimite = '2026-09-30';
// Concatenación con +
const conConcatenacion =
'Tarea de ' + responsable + ': ' + horas + ' h, vence el ' + fechaLimite;
// Template literal
const conPlantilla =
`Tarea de ${responsable}: ${horas} h, vence el ${fechaLimite}`;| Aspecto | Concatenación + |
Template literal |
|---|---|---|
| Legibilidad | Baja: el texto se rompe | Alta: el texto se lee entero |
| Espacios | Fáciles de olvidar | Se ven en el propio texto |
| Expresiones | Requieren paréntesis | ${horas * 2} directamente |
| Saltos de línea | Con \n |
Reales, escribiendo Intro |
| Riesgo de concatenar sin querer | Alto | Nulo: todo se convierte a texto |
Ese último punto es importante. Con + puedes acabar sumando por accidente:
const horasIvan = 12;
const horasLucia = 8;
console.log('Total: ' + horasIvan + horasLucia); // 'Total: 128' ← ¡mal!
console.log('Total: ' + (horasIvan + horasLucia)); // 'Total: 20' ← con paréntesis
console.log(`Total: ${horasIvan + horasLucia}`); // 'Total: 20' ← sin ambigüedadUsa template literals siempre que combines texto y variables. No hay ningún motivo para no hacerlo.
- Precedencia de operadores
Cuando una expresión mezcla operadores, JavaScript aplica un orden fijo llamado precedencia. De mayor a menor prioridad, en lo que te afecta ahora:
| Nivel | Operadores | Asociatividad | Ejemplo |
|---|---|---|---|
| 1 | () agrupación |
— | (2 + 3) * 4 → 20 |
| 2 | ?. acceso opcional |
Izquierda | tarea?.titulo |
| 3 | ++ -- sufijos |
— | i++ |
| 4 | ! ++ -- prefijos, typeof |
Derecha | !estaHecha |
| 5 | ** |
Derecha | 2 ** 3 ** 2 → 512 |
| 6 | * / % |
Izquierda | 2 + 3 * 4 → 14 |
| 7 | + - |
Izquierda | 10 - 3 - 2 → 5 |
| 8 | < > <= >= |
Izquierda | 12 > 8 |
| 9 | == != === !== |
Izquierda | 'alta' === 'alta' |
| 10 | && |
Izquierda | a && b |
| 11 | || y ?? |
Izquierda | a || b |
| 12 | ? : ternario |
Derecha | x > 0 ? 'sí' : 'no' |
| 13 | = += -= ??= |
Derecha | x += 1 |
Ejemplos que aclaran las reglas:
console.log(2 + 3 * 4); // 14, no 20: * tiene más precedencia que +
console.log((2 + 3) * 4); // 20: los paréntesis mandan
console.log(10 - 3 - 2); // 5: - es asociativo por la izquierda → (10-3)-2
console.log(2 ** 3 ** 2); // 512: ** es asociativo por la derecha → 2**(3**2)
console.log(!true && false); // false: ! se aplica antes que &&Un caso realista en Nómada Tareas:
const horasIvan = 12;
const horasLucia = 8;
const horasMarta = 6;
// Media del equipo: ¿qué crees que da?
console.log(horasIvan + horasLucia + horasMarta / 3); // 22 ← ¡mal!
console.log((horasIvan + horasLucia + horasMarta) / 3); // 8.67 ← correctoEn el primer caso, / se aplica antes que +, así que solo se dividen las horas de Marta.
Consejo definitivo: no memorices la tabla. Usa paréntesis. Cuestan dos caracteres y eliminan cualquier duda, tanto para el motor como para quien lea tu código. Nadie ha criticado nunca un paréntesis de más; muchos errores vienen de uno de menos.
- Aplicación: la carga de horas del equipo
Vamos a juntarlo todo en un caso real de Taller Nómada. Marta quiere saber cómo está repartida la carga de trabajo antes de asignar tareas nuevas.
'use strict';
// --- Datos de partida ---------------------------------------------
const MAX_HORAS_SEMANA = 40;
const responsable = 'Iván';
const horasTarea1 = 12; // Rediseñar la sala polivalente
const horasTarea2 = 8; // Cartelería del taller de serigrafía
const horasTarea3 = 4.5; // Revisar el catálogo de otoño
// Este dato podría no llegar (por ejemplo, si la tarea aún no se ha estimado)
const horasTarea4 = null;
// --- Cálculos ------------------------------------------------------
// 1. Horas asignadas. Con ?? tratamos la estimación que falta como 0
const horasAsignadas =
horasTarea1 + horasTarea2 + horasTarea3 + (horasTarea4 ?? 0);
// 2. Horas libres (podría salir negativo si está sobrecargado)
const horasLibres = MAX_HORAS_SEMANA - horasAsignadas;
// 3. Porcentaje de ocupación, redondeado
const porcentajeOcupacion = Math.round((horasAsignadas / MAX_HORAS_SEMANA) * 100);
// 4. Estado de la carga con un ternario encadenado
const estadoCarga =
porcentajeOcupacion >= 100 ? 'sobrecargado' :
porcentajeOcupacion >= 75 ? 'alto' :
porcentajeOcupacion >= 40 ? 'equilibrado' :
'con margen';
// 5. ¿Puede aceptar una tarea nueva de 8 horas?
const HORAS_TAREA_NUEVA = 8;
const puedeAceptarla = horasLibres >= HORAS_TAREA_NUEVA;
// --- Salida --------------------------------------------------------
console.log(`=== Carga semanal de ${responsable} ===`);
console.log(`Asignadas: ${horasAsignadas} h de ${MAX_HORAS_SEMANA} h`);
console.log(`Libres: ${horasLibres} h`);
console.log(`Ocupación: ${porcentajeOcupacion}% (${estadoCarga})`);
console.log(
`¿Puede asumir ${HORAS_TAREA_NUEVA} h más? ${puedeAceptarla ? 'Sí' : 'No'}`
);
// 6. Aviso solo si está en zona de riesgo, usando cortocircuito
porcentajeOcupacion >= 75 &&
console.warn(`Atención: ${responsable} está al ${porcentajeOcupacion}%`);Salida:
=== Carga semanal de Iván === Asignadas: 24.5 h de 40 h Libres: 15.5 h Ocupación: 61% (equilibrado) ¿Puede asumir 8 h más? Sí
Repasemos las decisiones que se han tomado:
horasTarea4 ?? 0trata la estimación ausente como cero horas. Con||habría funcionado igual aquí, pero si la estimación fuese legítimamente0,||la habría sustituido por 0 igualmente y en otros contextos daría problemas.??expresa exactamente la intención: "si no hay dato, usa 0".- Los paréntesis en
(horasAsignadas / MAX_HORAS_SEMANA) * 100no son estrictamente necesarios (/y*tienen la misma precedencia y se evalúan de izquierda a derecha), pero dejan clarísima la intención. Math.roundevita mostrar61.25%.- El ternario encadenado clasifica la carga en cuatro tramos. Está alineado para que se lea como una tabla.
puedeAceptarlaes un booleano con nombre de afirmación; en la salida se convierte a texto con otro ternario.- El cortocircuito
&&ejecuta el aviso solo si se supera el umbral. Aquí no se ejecuta, porque61 >= 75es falso.
Errores Comunes y Consejos
Errores comunes
- Sumar texto sin querer.
'12' + 8da'128'. Los datos de formularios llegan siempre como texto; conviértelos antes de operar. - Olvidar los paréntesis en un promedio.
a + b + c / 3no es la media. Es el error de cálculo más repetido del mundo. - Usar
||para valores por defecto numéricos.horas || 8convierte un0legítimo en8. Usa??. - Dividir sin comprobar el divisor.
x / 0daInfinitysilenciosamente y contamina todos los cálculos posteriores. - Mezclar
??con||o&&sin paréntesis. Es unSyntaxError. - Abusar de
x++dentro de expresiones.i++ + ++ies un acertijo, no código. - Poner
?.en todas partes. Silencia errores reales. Úsalo solo donde el valor pueda faltar legítimamente. - Confundir
=con==o===.if (estado = 'hecha')asigna en lugar de comparar, y siempre resulta verdadero.
Consejos
- Usa paréntesis siempre que haya más de un operador. La claridad vale más que la brevedad.
??para valores por defecto,||solo cuando quieras descartar también0y''.- Template literals para todo texto compuesto. Elimina de un plumazo los errores de concatenación.
- El ternario, para elegir un valor. Si necesitas ejecutar varias instrucciones, usa
if. - Nombra los resultados intermedios.
const porcentajeOcupacion = ...es infinitamente más legible que meter el cálculo entero dentro de unconsole.log. - Redondea al mostrar, no al calcular. Si redondeas en medio de una cadena de cálculos, acumulas error.
Ejercicios
Ejercicio 1: Predice el resultado
Escribe qué imprime cada línea y por qué:
console.log(2 + 3 * 4); // A
console.log('8' + 4); // B
console.log('8' - 4); // C
console.log(10 % 3); // D
console.log(2 ** 3 ** 2); // E
let i = 5;
console.log(i++); // F
console.log(i); // G
console.log(0 || 40); // H
console.log(0 ?? 40); // I
console.log('' ?? 'Sin asignar'); // J
console.log(null ?? 'Sin asignar');// K
console.log(!!'hecha'); // LEjercicio 2: Reparto rotativo de tareas
El equipo de Taller Nómada tiene tres personas en este orden: posición 0 = Marta, 1 = Iván, 2 = Lucía. Las tareas se asignan por turnos según su número.
Escribe un script que, dado un numeroTarea, calcule e imprima:
- La posición del equipo a la que corresponde (usa
%). - Si el número de tarea es par o impar.
- Un mensaje con template literal del estilo:
La tarea 7 corresponde a la posición 1 (número impar).
Pruébalo con los números 5, 6 y 7.
Ejercicio 3: Informe de carga de Lucía
Escribe un script que calcule la carga semanal de Lucía con estos datos:
- Máximo semanal: 40 horas.
- Tareas asignadas: 10, 6.5 y 3 horas.
- Una cuarta tarea cuya estimación todavía no existe (vale
null). - Ya ha dedicado 12 horas de las asignadas.
Calcula y muestra:
- Total de horas asignadas (la estimación ausente cuenta como 0, usando
??). - Horas pendientes de dedicar.
- Porcentaje de avance sobre lo asignado, redondeado a entero.
- Porcentaje de ocupación sobre el máximo semanal, redondeado.
- Si puede asumir una tarea nueva de 20 horas (booleano mostrado como "Sí"/"No" con un ternario).
- Un aviso con
console.warn, usando cortocircuito&&, solo si la ocupación supera el 40%.
Soluciones
Ejercicio 1
| Línea | Resultado | Explicación |
|---|---|---|
| A | 14 |
* tiene más precedencia que +: 2 + (3*4) |
| B | '84' |
Uno de los operandos es texto: + concatena |
| C | 4 |
- no concatena: convierte '8' a número |
| D | 1 |
El resto de dividir 10 entre 3 |
| E | 512 |
** asocia por la derecha: 2 ** (3**2) = 2**9 |
| F | 5 |
Forma sufija: devuelve el valor antiguo |
| G | 6 |
Pero la variable ya está incrementada |
| H | 40 |
0 es falsy, así que || pasa al segundo operando |
| I | 0 |
?? solo actúa ante null o undefined |
| J | '' |
La cadena vacía no es null ni undefined |
| K | 'Sin asignar' |
null sí activa ?? |
| L | true |
!! convierte a booleano; un texto no vacío es truthy |
Ejercicio 2
'use strict';
const numeroTarea = 7;
// 1. Posición en el equipo (3 personas: 0, 1, 2)
const TAMANO_EQUIPO = 3;
const posicion = numeroTarea % TAMANO_EQUIPO;
// 2. Par o impar
const esPar = numeroTarea % 2 === 0;
const paridad = esPar ? 'par' : 'impar';
// 3. Mensaje
console.log(
`La tarea ${numeroTarea} corresponde a la posición ${posicion} (número ${paridad}).`
);Resultados:
numeroTarea |
% 3 |
Posición | Paridad |
|---|---|---|---|
| 5 | 5 % 3 |
2 (Lucía) | impar |
| 6 | 6 % 3 |
0 (Marta) | par |
| 7 | 7 % 3 |
1 (Iván) | impar |
Ejercicio 3
'use strict';
// --- Datos ---------------------------------------------------------
const MAX_HORAS_SEMANA = 40;
const responsable = 'Lucía';
const horasTarea1 = 10;
const horasTarea2 = 6.5;
const horasTarea3 = 3;
const horasTarea4 = null; // todavía sin estimar
const horasDedicadas = 12;
// --- Cálculos ------------------------------------------------------
const horasAsignadas =
horasTarea1 + horasTarea2 + horasTarea3 + (horasTarea4 ?? 0);
const horasPendientes = horasAsignadas - horasDedicadas;
const porcentajeAvance = Math.round((horasDedicadas / horasAsignadas) * 100);
const porcentajeOcupacion = Math.round((horasAsignadas / MAX_HORAS_SEMANA) * 100);
const HORAS_TAREA_NUEVA = 20;
const horasLibres = MAX_HORAS_SEMANA - horasAsignadas;
const puedeAceptarla = horasLibres >= HORAS_TAREA_NUEVA;
// --- Salida --------------------------------------------------------
console.log(`=== Carga semanal de ${responsable} ===`);
console.log(`Asignadas: ${horasAsignadas} h`);
console.log(`Dedicadas: ${horasDedicadas} h`);
console.log(`Pendientes: ${horasPendientes} h`);
console.log(`Avance: ${porcentajeAvance}%`);
console.log(`Ocupación: ${porcentajeOcupacion}% de ${MAX_HORAS_SEMANA} h`);
console.log(
`¿Puede asumir ${HORAS_TAREA_NUEVA} h más? ${puedeAceptarla ? 'Sí' : 'No'}`
);
porcentajeOcupacion > 40 &&
console.warn(`Atención: ${responsable} supera el 40% de ocupación.`);Salida:
=== Carga semanal de Lucía === Asignadas: 19.5 h Dedicadas: 12 h Pendientes: 7.5 h Avance: 62% Ocupación: 49% de 40 h ¿Puede asumir 20 h más? Sí ⚠ Atención: Lucía supera el 40% de ocupación.
Puntos a destacar:
horasTarea4 ?? 0neutraliza el dato ausente. Sin ese operador,nullacabaría convirtiéndose a0de todos modos por coerción implícita, pero escribirlo de forma explícita documenta la intención y no depende de una conversión automática que quizá no controlas.- Los paréntesis en los porcentajes garantizan que primero se divide y después se multiplica por 100.
- El cálculo de
puedeAceptarla:horasLibresvale40 - 19.5 = 20.5, y20.5 >= 20estrue, así que el resultado es "Sí" por un margen muy justo de media hora. Si hubieras estimado la cuarta tarea en solo una hora, la respuesta habría cambiado. Este es exactamente el tipo de cálculo al filo que conviene que haga el programa y no una persona con una calculadora.
Conclusión
Ya sabes operar con datos. Manejas los aritméticos (+ - * / % **), incluido el módulo para repartos cíclicos, y conoces la doble personalidad del +. Distingues las formas prefija y sufija de ++ y --. Usas los operadores de asignación compuestos (+=, -=, *=...). Entiendes los lógicos &&, || y !, su evaluación de cortocircuito y el hecho de que devuelven un operando, no un booleano. Sabes cuándo usar ?? en lugar de || para valores por defecto, y aplicar ??= y ?. para trabajar con datos que pueden faltar. Empleas el ternario para elegir valores dentro de expresiones, prefieres los template literals a la concatenación, y sobre todo has aprendido la lección más rentable de todas: cuando dudes de la precedencia, pon paréntesis.
Con todo ello has construido el primer cálculo útil de Nómada Tareas: el informe de carga semanal de un miembro del equipo de Taller Nómada.
Pero has visto aparecer un fantasma varias veces: '8' + 4 da '84', null se convierte en 0 al sumar, 0 es falsy y '' también. Ese es el terreno donde más se tropieza. En la siguiente lección, Conversión de Tipos y Comparaciones, lo despejarás por completo: coerción implícita y explícita, la lista exacta de valores falsy y la diferencia entre == y ===. Es la lección que evita la mayoría de los errores de un principiante.
Curso de JavaScript: De Principiante a Avanzado
Módulo 1: Introducción a JavaScript
- ¿Qué es JavaScript?
- Configuración de tu Entorno de Desarrollo
- Tu Primer Programa en JavaScript
- Sintaxis y Conceptos Básicos de JavaScript
- Variables y Tipos de Datos
- Operadores Básicos
- Conversión de Tipos y Comparaciones
- El Proyecto del Curso: Nómada Tareas
Módulo 2: Estructuras de Control
- Sentencias Condicionales
- Bucles: for, while, do-while
- Sentencias Switch
- Control del Flujo: break, continue y Bucles Anidados
- Manejo de Errores con try-catch
Módulo 3: Funciones
- Definición y Llamada de Funciones
- Expresiones de Función y Funciones Flecha
- Parámetros y Valores de Retorno
- Ámbito y Closures
- Hoisting y el Contexto de Ejecución
- Funciones de Orden Superior
- Recursividad
Módulo 4: Objetos y Arrays
- Introducción a los Objetos
- Métodos de Objeto y la Palabra Clave
this - Arrays: Conceptos Básicos y Métodos
- Iteración sobre Arrays
- Buscar, Ordenar y Agregar Datos: find, sort y reduce
- Desestructuración de Arrays
- Desestructuración de Objetos, Spread y Rest
- JSON y Copias de Objetos
Módulo 5: Objetos y Funciones Avanzadas
- Prototipos y Herencia
- Clases y Programación Orientada a Objetos
- Encapsulación: Getters, Setters y Campos Privados
- Módulos e Importación/Exportación
- JavaScript Asíncrono: Callbacks
- Promesas y Async/Await
- El Bucle de Eventos y la Cola de Microtareas
- Iteradores y Generadores
Módulo 6: El Modelo de Objetos del Documento (DOM)
- Introducción al DOM
- Selección y Manipulación de Elementos del DOM
- Manejo de Eventos
- Propagación, Delegación y Eventos Personalizados
- Creación y Eliminación de Elementos del DOM
- Renderizado de Listas y Plantillas HTML
- Manejo y Validación de Formularios
Módulo 7: APIs del Navegador y Temas Avanzados
- Almacenamiento Local y de Sesión
- Fetch API y AJAX
- Peticiones Robustas: Errores, Timeouts y AbortController
- WebSockets
- Service Workers y Aplicaciones Web Progresivas (PWAs)
- APIs del Navegador Esenciales
- Introducción a WebAssembly
Módulo 8: Pruebas y Depuración
- Depuración de JavaScript
- Calidad de Código: ESLint, Prettier y Convenciones
- Pruebas Unitarias con Jest
- Dobles de Prueba: Mocks, Stubs y Spies
- Pruebas de Integración
- Pruebas de Extremo a Extremo con Cypress
Módulo 9: Rendimiento y Optimización
- Medir Antes de Optimizar: DevTools y Web Vitals
- Optimización del Rendimiento de JavaScript
- Gestión de Memoria
- Manipulación Eficiente del DOM
- Carga Perezosa y División de Código
Módulo 10: Frameworks y Librerías de JavaScript
- Por Qué Existen los Frameworks
- Introducción a React
- Gestión de Estado con Redux
- Conceptos Básicos de Vue.js
- Conceptos Básicos de Angular
- Elegir el Framework Adecuado
