A first splash into JavaScript

Estás leyendo la versión en inglés del artículo porque aún no existe una traducción para este idioma. ¡Ayúdanos a traducir este artículo!

Un primer acercamiento a JavaScript

Ahora que has aprendido algo acerca de la teoría de JavaScript y de lo que puedes hacer con él, vamos a darte un curso rápido sobre las características básicas de JavaScript con un tutorial completamente práctico. Aquí construirás paso a paso un juego sencillo de "Adivina el número".

Prerrequisitos: Conocimiento básico de computación, HTML, CSS y qué es JavaScript.
Objetivo: Tener un poco de experiencia escribiendo JavaScript, y conseguir al menos un entendimiento básico de lo que supone escribir un programa en JavaScript.

No esperes entender todo el código inmediatamente — por ahora sólo queremos presentarte los conceptos de alto nivel, y darte una idea de como funciona JavaScript (y otros lenguajes de programación). ¡Más adelante vas a volver ver estas características con mucho más detalle!

Nota: Muchas de las características que vas a ver en  JavaScript son las mismas en otros lenguajes de programación — funciones, bucles, etc.  La sintaxis del código es diferente, pero  los conceptos siguen siendo básicamente los mismos.

Pensando como un  programador

Una de las cosas mas difíciles de aprender en programación no es la sintaxis que necesitas aprender sino cómo aplicarla para resolver problemas del mundo real. Debes empezar a pensar como programador — esto generalmente implica buscar descripciones de qué necesita hacer tu programa, determinar qué características de código necesitas para alcanzar esas cosas y cómo hacer que funcionen juntas.

Ésto implica una combinación de trabajo duro, experiencia con la sintáxis de programación, y práctica - más un poquito de creatividad. Mientras más programes, más habilidoso serás haciéndolo. No te podemos prometer que vas a desarrollar un "cerebro de programador" en cinco minutos, pero, a lo largo de este curso, te vamos a dar muchas oportunidades de practicar el pensar como un programador.  

Teniendo ésto presente, veamos el ejemplo que vamos a construir en este artículo, y revisemos el proceso general de seccionarlo y divirlo en tareas tangibles.

Ejemplo — Juego adivina el número

En este artículo vamos a mostrarte como construir el juego que puedes ver abajo:

Juega un poco —Familiarízate con el juego antes de continuar.

Imaginemos que tu jefe te ha dado el siguiente resumen para crear este juego:

Quiero que crees un juego sencillo del tipo "adivina el número". Se debe elegir un número aleatorio entre 1 y 100, luego desafiar al jugador a adivinar el número en 10 intentos. Después de cada intento debería decirle al jugador si ha acertado o no - y si está equivocado, debería decirle si se ha quedado corto, o se ha pasado. También debería decir los números que ya se han probado anteriormente. El juego acabará una vez que el jugador acierte o cuando se acaben los intentos. Cuando el juego se acabe,  se le debe dar al jugador la opción de volver a jugar.

Al observar este resumen, lo primero que podemos hacer es empezar a desglosar el proyecto en tareas simples y realizables, con la mayor mentalidad de programador posible:

  1. Generar un número aleatorio entre 1 y 100.
  2. Registrar el número del intento en el que el jugador se encuentre. Empezando en 1.
  3. Darle al jugador una forma de adivinar cuál es el número.
  4. Una vez que se ha introducido un número, registrarlo en alguna parte para que el jugador pueda ver sus intentos previos.
  5. Siguente, comprobar si el número es correcto.
  6. Si es correcto:
    1. Mostrar un mesaje de felicitaciones.
    2. Hacer que el jugador no pueda introducir más intentos (esto arruinaría el juego).
    3. Mostrar un control que le permita al jugador reiniciar el juego.
  7. Si es incorrecto y al jugador todavía le quedan intentos:
    1. Decirle al jugador que ha fallado.
    2. Dejar al jugador intentarlo de nuevo.
    3. Incrementar el número de intentos en 1.
  8. Si el jugador falla y no le quedan turnos:
    1. Decirle al jugador que el juego se ha acabado.
    2. Hacer que el jugador no pueda introducir más intentos (esto arruinaría el juego).
    3. Mostrar un control que permita al jugador volver a empezar el juego.
  9. Una vez que el juego se reinicia,  asegurarse de que la lógica del juego y la IU estén completamente restablecidos, volver al paso 1.

Veamos cómo podemos transformar estos pasos en código, construyendo el ejemplo, y explorando las características de JavaScript a medida que lo hacemos.

Configuración inicial

Para empezar este tutorial, quisiéramos  que hicieras una copia local del archivo number-guessing-game-start.html (en vivo aquí). Ábrelo en tu editor de texto y en tu navegador web. De momento, puedes ver un sencillo encabezado, un párrafo de instrucciones y un espacio para introducir un intento de número, pero no hará nada por ahora.

El lugar donde agregaremos todo nuestro código es dentro del elemento <script> en la parte de abajo del HTML.

<script>

  // Tu código javascript va aqui.

</script>

Añadiendo variables para guardar los datos

Empecemos. En primer lugar, agrega las siguientes líneas dentro de tu elemento  <script>:

let randomNumber = Math.floor(Math.random() * 100) + 1;

const guesses = document.querySelector('.guesses');
const lastResult = document.querySelector('.lastResult');
const lowOrHi = document.querySelector('.lowOrHi');

const guessSubmit = document.querySelector('.guessSubmit');
const guessField = document.querySelector('.guessField');

let guessCount = 1;
let resetButton;

Esta sección del código establece las variables y constantes que necesitamos para almacenar los datos que nuestro programa utilizará. Las variables son básicamente contenedores de valores (como números o cadenas de texto). Creas una variable con la palabra clave let (o var) seguida de un nombre para tu variable (leerás más sobre la diferencia entre las palabras clave en un artículo futuro). Las constantes se utilizan para almacenar valores que no desea modificar y se crean con la palabra clave const. En este caso, estamos usando constantes para almacenar referencias a partes de nuestra interfaz de usuario; el texto dentro de algunas de ellas puede cambiar, pero los elementos HTML referenciados permanecen iguales.

Puedes asignar un valor a una variable o constante con un signo igual (=) seguido del valor que deseas darle.

En nuestro ejemplo:

  • A la primera variable - randomNumber -se le asigna un número al azar entre 1 y 100, calculado usando un algoritmo matemático.
  • Las tres primeras constantes sirven cada una para almacenar una referencia a los párrafos de resultados en nuestro HTML, y se usaran para insertar valores en los párrafos más adelante en el código: 
    <p class="guesses"></p>
    <p class="lastResult"></p>
    <p class="lowOrHi"></p>
  • Las siguientes dos constantes almacenan referencias al ingreso de texto y al botón "enviar" del formulario, y se usan para controlar las respuestas del jugador más adelante.
    <label for="guessField">Adivina el número: </label><input type="text" id="guessField" class="guessField">
    <input type="submit" value="Enviar intento" class="guessSubmit">
  • Nuestras dos variables finales almacenan un conteo de intentos de 1 (utilizado para tener un registro de cuántos intentos ha hecho  el jugador), y una referencia al botón de reinicio que aún no existe (pero existirá luego).

Note: Aprenderá mucho más sobre las variables más adelante en el curso, comenzando con siguiente artículo.

Funciones

A continuación, agrega lo siguiente debajo de tu código JavaScript anterior:

function checkGuess() {
  alert('Soy un marcador de posición');
}

Las funciones son bloques de código reutilizables que puedes escribir una vez y ejecutar muchas, ahorrando la necesidad de repitir el código todo el tiempo. Son realmente utiles. Hay varias maneras de definir funciones, pero por ahora nos concentraremos en un tipo simple. Aquí hemos definido una función usando la palabra clave function, seguida de un nombre, con paréntesis puestos después de él. Después de eso ponemos dos llaves ({ }). Dentro de las llaves se encuentra todo el código que queremos ejecutar cuando llamamos a la función.

Cuando queramos ejecutar el código, escribimos el nombre de la función seguido de los paréntesis.

Probemoslo ahora. Guarda tu código y actualiza la página en tu navegador. Luego ves a la developer tools JavaScript console, e ingresa la siguiente línea:

checkGuess();

Después de presionar  Return/Enter , debería aparecer una alerta que dice "Soy un marcador de posición"; hemos definido una función en nuestro código que crea una alerta cada vez que la llamamos.

Nota: Aprenderás mucho más sobre las funciones más adelante en el curso.

Operadores

Los operadores de JavaScript nos permiten realizar pruebas, cálculos matemáticos, unir cadenas y otras cosas similares.

Si aún no lo has hecho, guarda tu código, actualiza la página en tu navegador y abre el developer tools JavaScript console. Luego, podemos intentar escribir los ejemplos que se muestran a continuación — escribe cada una de las columnas "Ejemplo" exactamente como se muestra, presionando Return/Enter después de cada una, y mira los resultados que devuelven. Si no tienes fácil acceso a las herramientas de desarrollo del navegador, siempre puedes usar la sencilla consola integrada que se muestra a continuación:

Primero veamos los operadores aritméticos, por ejemplo:

Operador Descripción Ejemplo
+ Suma 6 + 9
- Resta 20 - 15
* Multiplicación 3 * 7
/ División 10 / 5

También se puede usar el operador + para unir cadenas de texto (en la programación, esto se llama concatenación). Intente ingresar las siguientes líneas, una por una:

let name = 'Bingo';
name;
let hello = ' saluda!';
hello;
let greeting = name + hello;
greeting;

También hay algunos operadores de atajo disponibles, llamados operadores de asignación aumentada. Por ejemplo, si quiere simplemente agregar una nueva cadena de texto a una existente y devolver el resultado, puede hacer esto:

name += ' saluda!';

Esto es equivalente a

name = name + ' saluda!';

Cuando estamos ejecutando pruebas de true/false (por ejemplo, dentro de condicionales — consulte abajo) usamos operadores de comparación. Por ejemplo:

Operador Descripción Ejemplo
=== Estricta igualdad (¿es exactamente lo mismo?) 5 === 2 + 4
!== No igualdad (¿no es lo mismo?) 'Chris' !== 'Ch' + 'ris'
< Menor que 10 < 6
> Mayor que 10 > 20

Condicionales

Volviendo a nuestra función checkGuess(), no queremos que sólo muestre un mensaje de marcador de posición. Queremos que compruebe si la respuesta del jugador es correcta o no, y que responda de manera apropiada.

En este punto, reemplaza tu actual función checkGuess() con esta versión:

function checkGuess() {
  let userGuess = Number(guessField.value);
  if (guessCount === 1) {
    guesses.textContent = 'Intentos anteriores: ';
  }
  guesses.textContent += userGuess + ' ';
 
  if (userGuess === randomNumber) {
    lastResult.textContent = '¡Felicidades! ¡Lo adivinaste!';
    lastResult.style.backgroundColor = 'green';
    lowOrHi.textContent = '';
    setGameOver();
  } else if (guessCount === 10) {
    lastResult.textContent = '!!!¡¡¡Fin del juego!!!!!!';
    setGameOver();
  } else {
    lastResult.textContent = '¡Equivocado!';
    lastResult.style.backgroundColor = 'red';
    if(userGuess < randomNumber) {
      lowOrHi.textContent = '¡El numero es muy bajo!!';
    } else if(userGuess > randomNumber) {
      lowOrHi.textContent = '¡El numero es muy grande!';
    }
  }
 
  guessCount++;
  guessField.value = '';
  guessField.focus();
}

Ésto es un montón de código - uf! Vayamos por cada sección para explicar qué hace.

  • La primera línea (línea 2  arriba) declara una variable llamada userGuess y establece su valor al introducido en el campo de texto. También pasamos este valor al método Number(), para asegurarnos que el valor es un número.  
  • Después nos encontramos con nuestro primer bloque de código condicional  (líneas 3-5 arriba). Un bloque de código condicional te permite ejecutar código de manera selectiva, dependiendo de si una condición es verdadera o no. Parece una función, pero no lo es. La forma más simple de un código condicional comienza con la palabra clave if, luego unos paréntesis, luego unas llaves. Dentro de los paréntesis incluímos un test. Si el test resulta verdadero, ejecutamos el código dentro de las las llaves. Si no, no lo hacemos y pasamos al siguente segmento de código. En este caso, el test analiza si la variable guessCount es igual a 1 (por ejemplo, si es el primer intento del jugador o no): 
    guessCount === 1
    Si lo es, hacemos que el contenido del texto del parrafo de intentos sea igual  a "intentos previos". Si no, no lo hacemos.
  • La línea 6 añade el valor actual de userGuess al final del párrafo de guesses, más un espacio en blanco así hay espacio entre cada intento mostrado.
  • El siguiente bloque (líneas 8-24 arriba) realiza un par de comprobaciones:
    • El primer if(){ } comprueba si la respuesta del jugador es igual al randomNumber establecido al comienzo de nuestro JavaScript. Si lo es, el jugador ha adivinado correctamente y ha ganado el juego, así que le mostramos al jugador un mensaje de felicitaciones en color verde, limpiamos los contenidos del cuadro de información de intentos Low/High, y ejecutamos una función llamada setGameOver(), que luego discutiremos.
    • Ahora hemos encadenado otro test al final del último usando la estructura else if(){ }. Éste comprueba si este turno es el último. Si lo es, el programa hace lo mismo que en el bloque anterior, excepto que en vez de mostrar un mensaje de felicitaciones, muestra uno de fin del juego.
    • El bloque final encadenado al final de este código (el else { }) contiene código que sólo es ejecutado si ninguno de los otros dos tests anteriores fue verdadero (por ejemplo si el si el jugador no tuvo ningún acierto pero aún le quedan intentos). En este caso, les decimos que son incorrectos, luego realizamos otro test condicional para comprobar si el intento fue más alto o más bajo que la respuesta, mostrando un mensaje para decirle si tiene que ir más alto o bajo, según sea apropiado.
  • Las últimas tres líneas en la función (línea 26-28 arriba) nos preparan para el siguiente intento. Añadimos 1 a la variable guessCount así el jugador usa un turno (++ es una operación de incremento - incremento en 1), y vaciamos el valor del campo de texto, dejándolo listo para introducir el siguiente intento.

Eventos

A esta altura, hemos implementado correctamente la función checkGuess(), pero no hará nada porque aún no la hemos llamado. Lo ideal sería llamarla cuando se presiona el botón de "Enviar intento", y para hacerlo necesitamos usar un evento. Los eventos son acciones que ocurren en el navegador, como clikear sobre un botón , o una página que se carga, un video que se reproduce, en respuesta a los cuales podemos ejecutar bloques de código. Los constructores que escuchan si se produce algún evento se llaman escuchadores de eventos, y los bloques de código ejecutados en respuesta al evento generado se llaman manejadores de eventos.   

Añade la siguiente línea debajo de tu función checkGuess():

guessSubmit.addEventListener('click', checkGuess);

Aquí agregamos un escuchador de evento al botón guessSubmit. Éste es un método que lleva dos valores de entrada (llamados argumentos) - el tipo de evento que queremos escuchar (en este caso click) como una cadena, y el código que queremos ejecutar cuando ocurra el evento (en este caso la función checkGuess() - fíjate que no necesitamos especificar los paréntesis de la función cuando lo escribimos dentro de addEventListener()).

Prueba a guardar y refrescar tu código, y ahora tu ejemplo debería funcionar hasta cierto punto. El único problema es que si tu aciertas la respuesta correcta o te quedas sin intentos, el juego dejará de funcionar porque todavía no hemos definido la función setGameOver() que se tiene que ejecutar una vez que el juego ha acabado. Agreguemos el código que falta y completemos la funcionalidad del ejemplo.

Finalizando la funcionalidad del juego

Agreguemos esa función setGameOver al pie de nuestro código y luego repasémoslo. Agrega ésto ahora, debajo del resto de tu JavaScript:

function setGameOver() {
  guessField.disabled = true;
  guessSubmit.disabled = true;
  resetButton = document.createElement('button');
  resetButton.textContent = 'Iniciar nuevo juego';
  document.body.appendChild(resetButton);
  resetButton.addEventListener('click', resetGame);
}
  • Las primeras dos líneas deshabilitan la entrada de texto y el botón al fijar sus propiedad deshabilitado a verdadero. Ésto es necesario, porque si no lo hiciéramos, el usuario podría seguir enviando más intentos aunque el juego hubiera acabado. 
  • Las tres líneas siguientes generan un elemento <button>, fijan su etiqueta de texto a "Comenzar nuevo juego", y lo añaden al pie de nuestro HTML.  
  • La línea final establece un escuchador de eventos en nuestro botón nuevo de manera que cuando se haga click sobre él, una función llamada resetGame() sea ejecutada.

Ahora tenemos que definir esta función también! Agrega el siguiente código, de nuevo al final de tu JavaScript:

function resetGame() {
  guessCount = 1;

  const resetParas = document.querySelectorAll('.resultParas p');
  for (let i = 0 ; i < resetParas.length ; i++) {
    resetParas[i].textContent = '';
  }

  resetButton.parentNode.removeChild(resetButton);

  guessField.disabled = false;
  guessSubmit.disabled = false;
  guessField.value = '';
  guessField.focus();

  lastResult.style.backgroundColor = 'white';

  randomNumber = Math.floor(Math.random() * 100) + 1;
}

Este largo bloque de código reinicia todo completamente al estado en el que estaba el juego al comienzo, así el jugador puede jugar nuevamente :

  • Establece el guessCount de nuevo a 1
  • Limpia todos los párrafos de información.
  • Quita de nuestro código el botón de reinicio.
  • Habilita los elementos del formulario, y vacía y centra el foco en el campo de texto, quedando listo para otro intento.
  • Quita el color de fondo del párrafo lastResult.
  • Genera un nuevo número al azar distinto al de la anterior partida.

A esta altura deberias tener un juego (simple) funcionando  - felicidades!

Lo único que nos queda por hacer en este artículo es hablar acerca de  otras caractéristicas importantes del código que tal vez ya has visto aunque no lo hayas notado.

Bucles

Una parte del código, la cual tenemos que examinar más en detalle, es el bucle for. En programación, los bucles son un concepto muy importante que te permiten ejecutar un segmento de código una y otra vez, hasta que se cumpla una condición determinada.

Para comenzar, ve nuevamente a tu consola JavaScript de las herramientas de Desarrollador del navegador e introduce lo siguiente:

for (let i = 1 ; i < 21 ; i++) { console.log(i) }

¿Qué sucedió? Los números del 1 al 20 se imprimieron en la consola. Ésto es debido al bucle. Un bucle for lleva tres valores (argumentos) de entrada:

  1. Un valor de inicio: En este caso, comenzamos a contar en 1, pero este número podría ser el que tu quieras. También puedes reemplazar i con cualquier nombre que quieras, pero por convención se usa i porque es corto y fácil de recordar.
  2. Una condición de salida: Aquí hemos especificado i < 21 - el bucle va a continuar hasta que i deje de ser menos de 21. Cuando i alcance el 21, el bucle dejará de ser ejecutado.

  3. Un incremento: Hemos especificado i++, que significa "agregar 1 a i". El bucle se va a ejecutar una vez por cada valor de i hasta que i alcance un valor de 21. En este caso, simplemente estamos imprimiendo el valor de i en la consola en cada iteración usando console.log().

Ahora echémosle un vistazo nuevamente al bucle en nuestro juego de adivinar el número - lo siguiente esta dentro de la función resetGame():

let resetParas = document.querySelectorAll('.resultParas p');
for (let i = 0 ; i < resetParas.length ; i++) {
  resetParas[i].textContent = '';
}

Este código crea una variable que contiene una lista de todos los párrafos dentro de <div class="resultParas"> usando el método querySelectorAll(), luego realiza bucles a través de cada uno, eliminando el contenido textual a su paso.

Una pequeña discusión acerca de objetos

Agreguemos una última mejora antes de entrar en esta discusión. Agrega la siguiente línea justo debajo de la línea var resetButton; cerca del borde superior de tu JavaScript, luego guarda tu archivo:

guessField.focus();

Esta línea utiliza el método focus() para poner el cursor de texto en el campo de texto <input> apenas se carga la página, lo que significa que el usuario puede comenzar a ingresar su primer intento inmediatamente, y no hace falta que primero haga click en el campo de formulario. Es sólo una pequeña modificación pero mejora la usabilidad - dándole al usuario una buena señal visual acerca de qué tiene que hacer para jugar el juego.

Analicemos que está ocurriendo aqui un poquito más a fondo. En JavaScript todo es un objeto. Un objeto es una colección de funcionalidad relacionada almacenada en un solo grupo. Tú puedes crear tus propios objetos pero eso es bastante avanzado y no lo vamos a ver sino hasta mucho más adelante en el curso. Por ahora, sólo discutiremos de manera breve los objetos integrados que contiene tu navegador, los cuales te permiten realizar un montón de cosas útiles.

En este caso en particular, primero creamos una constante guessField que almacena una referencia al campo de entrada de texto en nuestro HTML - la siguiente línea puede encontrarse entre nuestras declaraciones de variables cerca del borde superior:

const guessField = document.querySelector('.guessField');

Para conseguir esa referencia, usamos el método querySelector() del objeto document. querySelector() recibe un parametro - un selector CSS que selecciona el elemento al cual tú quieres hacer referencia.    

Como guessField ahora contiene una referencia a un elemento <input>,  tendrá acceso a una cantidad de propiedades (básicamente, variables almacenadas dentro de objetos, algunas de las cuales no pueden cambiar su valor) y métodos (básicamente, funciones almacenadas dentro de objetos). Un método disponible para elementos de entrada es focus(), así que ahora podemos usar esta línea para hacer foco en la entrada de texto

guessField.focus();

Las variables que no contienen referencias a elementos del formulario, no tendrán focus() disponible. Por ejemplo, la variable guesses contiene una referencia a un elemento <p>, y guessCount contiene un número.

Jugando con los objetos del navegador

Juguemos un poquito con algunos objetos del navegador.

  1. Antes que nada, abre tu programa en un navegador.
  2. Luego, abre tus herramientas de desarrollador del navegador y asegúrate que la pestaña de consola de JavaScript esté abierta.
  3. Escribe guessField y la consola te mostrará que la variable contiene un elemento <input>. También verás que la consola autocompleta nombres de objetos que existen dentro del entorno de ejecución, incluídas tus variables!
  4. Ahora escribe lo siguiente:
    guessField.value = 'Hola';
  5. La propiedad value representa el valor mostrado en el campo de texto. Verás que al ingresar este comando, hemos cambiado este valor!
  6. Ahora intenta ingresar guesses y presionar enter. La consola te mostrará que la variable contiene un elemento  <p>.
  7. Ahora intenta ingresar la siguiente línea:
    guesses.value
  8. El navegador te dará un undefined como resultado porque value no existe en los párrafos.
  9. Para cambiar el texto dentro de un párrafo, necesitas la propiedad textContent. Prueba con ésto:
    guesses.textContent = '¿Dónde está mi párrafo?';
  10. Ahora, sólo por diversión, intenta ingresar las líneas que figuran debajo, una por una:
    guesses.style.backgroundColor = 'yellow';
    guesses.style.fontSize = '200%';
    guesses.style.padding = '10px';
    guesses.style.boxShadow = '3px 3px 6px black';
    Cada elemento en una página tiene una propiedad style, que en sí misma contiene un objeto cuyas propiedades contienen todos los estilos CSS aplicadas a ese elemento. Ésto permite fijar de manera dinámica nuevos estilos de CSS sobre elementos usando JavaScript. 

Terminamos por ahora...

Así que eso es todo para construir el ejemplo - llegaste al final, bien hecho! Prueba tu código final, o juega aquí con la versión terminada. Si no puedes lograr que tu ejemplo funcione, contrástalo con el código fuente.

En este módulo