← JavaScript: el lenguaje

Sesión 1

Datos, tipos y expresiones

Tres horas. Media hora para entender dónde se ejecuta tu código, cómo se guarda un dato y qué hace JavaScript cuando mezclas tipos, y dos horas y media prediciendo resultados y comprobándolos uno a uno.

Hoy · Hoja de ruta

  1. 1. Aprende: Dónde se ejecuta JavaScript, cómo se enlaza con una página, qué tipos de dato existen y por qué se compara siempre con el triple igual.
  2. 2. Haz: Enlaza tu primer script, modela un producto con variables y predice el resultado de una batería de expresiones antes de ejecutarlas.
  3. 3. Comprueba: Aciertas la mayoría de las predicciones y sabes explicar las que fallas.

Antes de empezar · 5 minutos, sin apuntes

  1. ¿Qué cosas de una web crees que no puede hacer el HTML por sí solo?
  2. En la UD2, ¿cómo comprobabas que la hoja de estilos se había cargado?
  3. ¿Qué crees que vale "3" + 1? ¿Y "3" - 1?

Se explica

25 minutos · conceptos y demostración

La sesión entera gira alrededor de una idea incómoda: JavaScript casi nunca se niega a hacer algo. Convierte, adivina y devuelve un resultado. Entender qué devuelve y por qué es lo que separa programar de probar cosas.

Un lenguaje que vive dentro del navegador

Todo navegador moderno lleva dentro un motor de JavaScript: un programa que lee tu código y lo ejecuta. No hay que instalar nada ni compilar nada. Abres la consola, escribes una expresión y te responde.

2 + 3
"Pixel" + "Store"
10 / 4
new Date().getFullYear()

Escribir en la consola sirve para probar; lo que se conserva va en un fichero. Se crea js/main.js y se enlaza desde el head con defer:

console.log("El código se está ejecutando");
<script src="js/main.js" defer></script>

defer

Le dice al navegador: descarga el fichero mientras lees el documento, y ejecútalo cuando el documento esté completo. Sin defer, el código se ejecuta antes de que exista la página, y en la UD4 eso significaría buscar elementos que todavía no están.

Forma Cómo se escribe Cuándo
Fichero externo Un .js enlazado con script src Siempre
Bloque en la página Código dentro de un script en el documento Pruebas rápidas
En un atributo onclick="..." en la etiqueta Nunca en este módulo

Las razones son las mismas que en CSS: reutilización, caché y mantener separadas las tres capas. Un onclick mete comportamiento dentro de la estructura, que es justo lo que llevamos dos unidades evitando.

Leer un error en vez de asustarse

Uncaught ReferenceError: precioTotal is not defined
    at main.js:1:13

Ese es el aspecto de un error provocado por escribir console.log(precioTotal); sin haber declarado esa variable. Tiene tres partes y las tres importan: el tipo de error (ReferenceError), el mensaje (is not defined) y la posición (main.js, línea 1, columna 13). Con eso ya sabes qué mirar antes de tocar nada.

El primer error es el que hay que arreglar

Cuando algo falla, la consola suele llenarse. Casi siempre los errores siguientes son consecuencia del primero. Sube arriba del todo, arregla ese, recarga y vuelve a mirar.

Guardar un valor con un nombre

const nombre = "Teclado mecánico";
const precio = 89.9;
let stock = 12;
Palabra Se puede reasignar Cuándo se usa
const No Por defecto, siempre que el valor no cambie
let Sí Cuando el valor tiene que cambiar
var Sí Nunca en código nuevo

Empieza siempre por const

Declara con const y cámbialo a let solo cuando el propio lenguaje te obligue con un error. Así, al leer el código, un let significa algo: «esto cambia, presta atención».

var no lo usamos porque no respeta los bloques y permite redeclarar la misma variable sin avisar. Aparecerá en código antiguo y en respuestas de IA; sustitúyelo.

const texto = "Teclado";        // string
const numero = 89.9;            // number
const disponible = true;        // boolean
const sinValor = null;          // null: vacío a propósito
let noAsignada;                 // undefined: todavía no tiene valor

La diferencia entre null y undefined se pregunta mucho y es sencilla: undefined es «nadie le ha dado valor»; null es «alguien decidió que estuviera vacío». Para preguntar el tipo está typeof, con una rareza histórica que conviene conocer:

typeof "Teclado"   // "string"
typeof 89.9        // "number"
typeof true        // "boolean"
typeof undefined   // "undefined"
typeof null        // "object"  ← un error histórico del lenguaje

Para construir texto se usan plantillas, escritas con acento grave, que permiten insertar valores con ${} y ocupar varias líneas:

const producto = "Teclado";
const unidades = 3;

const linea = "Has elegido " + unidades + " × " + producto;
const mejor = `Has elegido ${unidades} × ${producto}`;

A partir de aquí, siempre plantillas: concatenar con + es donde nacen la mitad de los espacios perdidos.

JavaScript tiene además un único tipo numérico, en coma flotante, y eso trae una sorpresa clásica:

0.1 + 0.2        // 0.30000000000000004

El comportamiento no constituye un defecto de JavaScript, sino una consecuencia de la representación binaria de los decimales. Con dinero se trabaja en céntimos, con enteros, o se redondea al presentar con toFixed(2), que devuelve texto.

La conversión automática, el gran tropiezo

JavaScript, cuando mezclas tipos, convierte por su cuenta:

"3" + 1      // "31"   con texto, el + concatena
"3" - 1      // 2      el - no sabe concatenar: convierte a número
"3" * "2"    // 6
true + 1     // 2      true vale 1

La regla práctica: la suma con un texto a un lado concatena; el resto de operadores aritméticos convierten a número.

Esto no es una curiosidad de examen. Es exactamente el fallo que te espera en la UD4, cuando leas el valor de un campo:

const introducido = "10";      // lo que da un campo de formulario
introducido + 5                // "105"   ← el error clásico
Number(introducido) + 5        // 15      ← lo correcto

Convierte tú, en el borde de tu programa

Todo lo que entra desde fuera —un formulario, una URL, un fichero, una API— llega como texto. Conviértelo en el momento de leerlo y opera después con números de verdad. Si conviertes tarde, arrastras el texto por medio programa.

Y comprueba el resultado: Number("hola") da NaN, que es un número que significa «esto no era un número».

Comparar, y qué cuenta como verdadero

5 == "5"     // true   compara después de convertir
5 === "5"    // false  compara valor y tipo

En este módulo se compara con el triple igual

Siempre. El doble igual convierte antes de comparar, y esas conversiones tienen casos que nadie recuerda de memoria. Escribir un carácter más no cuesta nada y elimina una familia entera de errores.

En un if, JavaScript pregunta si el valor es truthy o falsy. Los falsos son exactamente estos seis:

false, 0, "", null, undefined, NaN

Todo lo demás es verdadero, incluidos "0", "false", [] y {}. Esto explica un fallo muy común:

const unidades = 0;

if (unidades) {
  // no entra: 0 es falsy, aunque sea un valor perfectamente válido
}

if (unidades !== undefined) {
  // esto sí comprueba lo que querías comprobar
}

En los operadores lógicos hay una distinción que importa por lo mismo:

true && false     // false   y
true || false     // true    o
!true             // false   no
const nombre = entrada || "Sin nombre";   // si entrada es falsy: también con 0 o ""
const stock = recibido ?? 0;              // solo si es null o undefined

El segundo suele ser el que quieres: el || también sustituiría un 0 legítimo.

Nombrar bien no es cosmética

const p = 89.9;              // ¿precio? ¿peso? ¿página?
const precioConIva = 89.9;   // se lee solo

En este módulo: camelCase, en castellano o en inglés pero sin mezclar, nombres que digan qué contienen, y MAYUSCULAS_CON_GUION solo para constantes de configuración.

Se trabaja

150 minutos · práctica sobre tu propio proyecto

Los dos primeros pasos ponen el código en marcha. Del tercero en adelante se trabaja la única habilidad que de verdad se evalúa hoy: predecir qué va a hacer el lenguaje antes de ejecutarlo.

Paso 1 · Tu primer script · 20 min

  1. Crea js/main.js y enlázalo en index.html con defer.
  2. Escribe tres console.log con tu nombre, el nombre de tu proyecto y el año actual calculado.
  3. Provoca un error a propósito y anota su tipo, su mensaje y su línea.
  4. Corrígelo.
  5. Enlaza el mismo fichero en el resto de páginas.

Antes de continuar: el mensaje aparece en la consola de las cuatro páginas, y sabes demostrarlo sin recurrir a que «parece que funciona».

Paso 2 · La ficha de un producto · 30 min

En js/main.js, con datos de tu tema:

  1. Declara seis variables que describan un producto: nombre, precio, categoría, unidades, disponible y descripción.
  2. Elige const o let justificando cada elección en un comentario.
  3. Escribe con una plantilla una línea de resumen legible.
  4. Calcula el precio con IVA y muéstralo con dos decimales.
  5. Comprueba con typeof que cada variable tiene el tipo que esperabas.
  6. Reasigna una const a propósito, lee el error y escribe qué protege exactamente.
Consultar · operadores y conversión explícita
7 + 2      // 9
7 - 2      // 5
7 * 2      // 14
7 / 2      // 3.5
7 % 2      // 1   resto de la división
7 ** 2     // 49  potencia

El resto, %, parece anecdótico y no lo es: es como se detecta un número par (n % 2 === 0) o se recorre algo en ciclo.

let stock = 10;
stock += 5;    // 15
stock -= 2;    // 13
stock++;       // 14

Conversión explícita, que es la que vas a escribir tú:

Number("10")       // 10
Number("10,5")     // NaN   ← la coma no es el separador decimal
parseInt("10px")   // 10    se queda con lo que puede leer
parseFloat("10.5") // 10.5
Number.isNaN(Number("hola"))   // true

El redondeo al presentar:

const total = 0.1 + 0.2;
total.toFixed(2);            // "0.30"  ← devuelve texto
Number(total.toFixed(2));    // 0.3

Paso 3 · Predice y comprueba · 35 min

Es el trabajo central de la sesión. Crea js/predicciones.js. Para cada expresión, escribe primero tu predicción en un comentario y solo después ejecútala:

"5" + 3
"5" - 3
5 + true
"10" > 9
"10" > "9"
0 === -0
NaN === NaN
[] == false
null + 1
undefined + 1
Number("")
Boolean("false")

Las predicciones escritas antes son la tarea; ejecutar las doce expresiones son dos minutos. Cuando falles una, no te limites a corregir el comentario: escribe qué regla habías aplicado mal. Ese renglón vale más que el acierto.

Ver respuestas

De arriba abajo: "53", 2, 6, true (convierte a número), false (compara texto con texto, y el «1» va antes que el «9»), true, false (nada es igual a NaN), true, 1, NaN, 0, true (es un texto no vacío).

Paso 4 · La entrada llega como texto · 25 min

Sobre tu proyecto, y simulando lo que en la UD4 vendrá de un formulario:

  1. Declara tres datos «de formulario» como textos: unas unidades, un precio y un código.
  2. Conviértelos correctamente en el momento de leerlos, no más tarde.
  3. Calcula un total y comprueba que no es NaN.
  4. Escribe una comprobación que detecte una entrada no numérica y avise en vez de calcular con basura.
  5. Prueba tu comprobación con estos cinco valores y anota qué hace con cada uno: "12", "12,5", "", " 7 " y "doce".

El quinto apartado es el que enseña: dos de los cinco pasan por número sin serlo del todo, y la comprobación ingenua los deja entrar.

Paso 5 · Nombres que se leen solos · 20 min

Este fragmento funciona y es ilegible:

const x = 89.9;
const y = 3;
const z = x * y;
const w = z * 1.21;
let f = false;
const d = "Teclado mecánico compacto con retroiluminación";
const D = 12;
const precio_final = w;
  1. Renómbralo entero. Cada nombre debe decir qué contiene.
  2. Hay dos nombres que además incumplen el criterio del módulo por su forma, no por su significado: localízalos y corrígelos.
  3. Decide en cada caso si va const o let, y justifica los que cambies.
  4. Aplica después la misma revisión a tu propio main.js: si algún nombre necesita un comentario para entenderse, el nombre está mal.

Paso 6 · Predicciones cruzadas · 20 min

Escribe cinco expresiones tramposas para un compañero, con su respuesta apuntada aparte. Deben cumplir dos condiciones: que usen solo lo visto hoy, y que tú sepas explicar por qué dan lo que dan.

Intercambiadlas. Sobre las que recibas:

  1. Predice cada una por escrito.
  2. Ejecútalas y compara.
  3. En las que falles, pide la explicación a su autor y comprueba si te convence. Si el autor no sabe explicarla, esa expresión no valía como trampa: era una casualidad.

Ampliación si has completado el trabajo

Primero termina y comprueba los seis pasos. Los dos retos siguen la misma idea: el lenguaje no falla, responde, y hay que saber qué va a responder.

Reto 1 · Por qué "10" > "9" es falso

"10" > 9      // true
"10" > "9"    // false
  1. Explica por escrito qué comparación hace cada una, y por qué el resultado cambia al poner comillas en el segundo operando.
  2. Predice y comprueba estas otras cinco: "2" > "10", "b" > "a", "B" > "a", [] + [], [] + {}.
  3. La tercera sorprende a casi todo el mundo. Averigua qué se está comparando en realidad y escríbelo.
  4. Enuncia en una frase la regla general: cuándo compara JavaScript como números y cuándo como texto.
  5. Relaciónalo con un caso real: una lista de códigos de producto ordenada alfabéticamente frente a la misma lista ordenada numéricamente. ¿Dónde acaba el "10"?

Reto 2 · El formulario que miente

Estos son los valores que un formulario real puede entregar para un campo de cantidad. Todos son texto.

"12"        un número normal
"012"       con cero delante
"12,5"      con coma decimal, como se escribe en español
"12.5"      con punto decimal
"  12  "    con espacios alrededor
""          el campo vacío
"1e3"       notación científica
"12px"      alguien pegó algo de más
"doce"      texto sin ningún número
"-3"        negativo
"Infinity"  literalmente

Escribe una sola función de validación que decida, para cada uno, si es una cantidad aceptable y cuál es su valor numérico. Antes de escribirla:

  1. Decide qué debería aceptar tu programa y qué no. No hay una respuesta única: "12,5" puede ser un error del usuario o una cantidad perfectamente legítima escrita como se escribe aquí. Documenta tu criterio.
  2. Prueba qué hace Number() con cada uno, y qué hace parseInt(). Anota los tres casos en los que no coinciden.
  3. Dos de la lista pasan Number() sin ser cantidades razonables. Identifícalos y explica qué comprobación adicional hace falta.
  4. Comprueba tu función contra los once valores y construye una tabla con lo que aceptas, lo que rechazas y lo que conviertes antes de aceptar.
Objetivo mínimoEl script cargando en las cuatro páginas, el producto modelado con tipos correctos y las doce predicciones escritas y comprobadas.
Si lo tienesLa conversión de entradas con su comprobación de NaN, el fragmento renombrado y las predicciones cruzadas contestadas.
RetoLa regla general de comparación enunciada con sus cinco casos, y la función de validación probada contra los once valores del formulario.

Cierre

5 minutos · comprobación y recuerdo

Lista de verificación de la sesión

  • Tu código se ejecuta desde un fichero externo en todo el sitio.
  • Distingues const de let y usas const por defecto.
  • Construyes texto con plantillas, no con el operador de suma.
  • Conviertes la entrada al leerla y compruebas NaN.
  • Comparas siempre con el triple igual.
  • Tienes un fichero de predicciones que puedes releer cuando algo raro pase.

Antes de cerrar · 3 minutos, sin mirar

  1. ¿Qué tres datos te da un error de la consola?
  2. ¿Por qué evitamos onclick en el HTML?
  3. ¿Qué diferencia hay entre null y undefined?
  4. ¿Qué devuelve toFixed(2), un número o un texto?
  5. Enumera los seis valores falsy.
  6. ¿Por qué "5" + 3 y "5" - 3 dan cosas distintas?
Ver respuestas

1 · El tipo de error, el mensaje, y el fichero con su línea y su columna.

2 · Porque mezcla comportamiento con estructura, y pierde la reutilización y la caché del fichero externo.

3 · undefined es que no se le ha dado valor; null es un vacío puesto a propósito.

4 · Un texto. Si vas a seguir calculando, conviértelo con Number().

5 · false, 0, "", null, undefined y NaN.

6 · Porque el + con un texto a un lado concatena, y el - no sabe concatenar: convierte los dos operandos a número.

Microprueba semanal 1 · 5–10 minutos

Individual, sin IA y sin apuntes.

  1. Di qué imprime "5" + 3 y qué imprime "5" - 3, y por qué son distintos.
  2. Declara tres variables eligiendo const o let, y justifica cada elección en cinco palabras.
  3. Enumera los seis valores falsy.