Читать книгу: «JavaScript: Guía completa»

Шрифт:

JavaScript

Guía completa

Alessandra Salvaggio, Gualtiero Testa

JavaScript

Guía completa

Alessandra Salvaggio, Gualtiero Testa


Sumario

Introducción

1. JavaScript

El renacer de JavaScript

La popularidad de JavaScript

JavaScript y ECMAScript

Los hermanos de JavaScript

2. Cómo escribir código JavaScript

Herramientas de trabajo

Integrar los comandos JavaScript en las páginas HTML

Advertencia

3. ¡Hola mundo!

Un poco de dinamismo

4. Trabajar con cadenas

Cadenas multilínea

Insertar el backtick o acento grave

5. Los bucles

La consola

6. Funciones

Pasar parámetros a las funciones

Funciones anónimas

El área de validez de variables y constantes

7. Formularios y eventos

Operar con cadenas de texto

Gestores de eventos

8. Expresiones regulares

Definir los patrones para las expresiones regulares

Aplicar expresiones regulares

9. Objetos

Ejemplo práctico

10. Arrays asociativos

Utilizar objetos para crear arrays asociativos

Array asociativo completado durante la ejecución del código

11. New: crear instancias de objetos

12. Modo estricto

¿Por qué utilizar el modo estricto?

13. This

Call y Apply

Bind

14. Funciones avanzadas

Las funciones flecha

Gestión de this

Funciones utilizadas como método

¿Qué modo utilizar para las funciones?

Observaciones finales

15. JSON

Procesar JSON con JavaScript

Un sitio para realizar pruebas

16. AJAX y REST

La llamada POST

Servicios REST

17. Objetos avanzados

Parámetros rest

Operador spread

18. DOM

El modelo

Traversing

Crear nodos

Event delegation

19. BOM

Pantalla

Location

Historial de navegación

Navigator

Ventanas

Temporización

Cookies

20. Canvas

Las coordenadas de los lienzos

Dibujar trazos

Dibujar con curvas de Bézier

Dibujar arcos y circunferencias

Estilos de línea

Degradados

Imágenes

Texto

Sombras

Composiciones

Animaciones

21. Geolocalización

Recuperar las coordenadas geográficas

Gestionar errores

Opciones

Mostrar un mapa de Google

22. Web worker

Comunicación bidireccional

Pasar objetos

Finalizar el worker

Gestión de errores

Importar scripts externos

Objetos a los cuales puede acceder el worker

Workers compartidos

23. El arrastre

Arrastrar otros objetos y recuperar información sobre los objetos arrastrados

Arrastrar un archivo

A1. Visual Studio Code

Trabajar por carpetas y archivos

Instalar ESLint

Abrir un archivo HTML en el navegador desde VS Code

A2. Instalar XAMPP

Utilizar XAMPP

Índice analítico

Introducción

Es cierto que JavaScript no es un lenguaje nuevo en el panorama de la programación para web pero, en los últimos años, ha experimentado un interés y un éxito renovados.

JavaScript existe desde hace más de 20 años y ha vivido, con más o menos suerte, la evolución del mundo de Internet.

A veces desairado y considerado un lenguaje más para aficionados que para profesionales, a veces adorado por su versatilidad y simplicidad, en los últimos años está viviendo una auténtica nueva juventud.

Estándar y, por lo tanto, más riguroso según el IEEE, el lenguaje inventado por Brendan Eich dentro del proyecto para el navegador Netscape Navigator cada vez se utiliza más para grandes proyectos, no solo en entornos web. Actualmente existen aplicaciones enteras desarrolladas en JavaScript.

Por evidentes razones de espacio y para no dispersar demasiado el discurso, este libro se centrará esencialmente en el uso de JavaScript en el contexto web.

Los lectores deberán conocer en profundidad el lenguaje HTML (por descontado) y tener conocimientos de CSS; en cambio, no necesitarán competencias especiales en el campo de la programación.

El libro empieza por conceptos básicos hasta llegar a argumentos más avanzados.

El camino es exigente pero, en estas páginas, trataremos de guiar al lector paso a paso para que pueda llegar a ser autónomo y desarrollar sus propios proyectos en JavaScript.

Podéis descargar los archivos para llevar a cabo los ejercicios del libro en la página www.marcombo.info, con el código JAVA2.


JavaScript

JavaScript es un lenguaje de programación nacido hace más de 20 años. ¿Vale la pena aprenderlo hoy? Intentemos responder a dicha pregunta haciendo un recorrido por la evolución de este lenguaje.

JavaScript (con las letras J y S en mayúsculas y muchas veces indicado con la sigla JS) es un lenguaje de programación creado en 1995 dentro del proyecto para el navegador Netscape Navigator con el objetivo de hacer la navegación web más dinámica e interactiva.

Tal y como fue concebido inicialmente, los programas escritos en JavaScript son ejecutados por el navegador web y, por lo tanto, en el navegador del usuario y no en el servidor donde se encuentra hospedado el sitio.

Por su características, JavaScript es un lenguaje un poco anómalo y no fácilmente clasificable: su diseñador, Brendan Eich, tomó decisiones muy criticadas por los puristas de la programación, puesto que JavaScript reúne en sí mismo, de manera no siempre armoniosa, características de varios lenguajes conocidos en la época de su nacimiento.

El resultado parecía algo un poco “híbrido”: por ejemplo, su sintaxis procede en gran parte de la del lenguaje Java (por eso se denominó JavaScript, aunque la sintaxis es la única conexión entre ambos lenguajes), pero también se aleja de él en puntos fundamentales, “filosóficos”. Un ejemplo evidente: JavaScript define, igual que Java (y otros lenguajes como SmallTalk) el concepto de objeto (volveremos a este concepto en el transcurso de este libro), pero, por sus características, no puede definirse como un auténtico lenguaje orientado a objetos.

JavaScript posee características de lenguajes funcionales (como Scheme) y, de hecho, define funciones como elementos de primera clase (first class function), pero no es un lenguaje funcional puro.

A este “pecado original”, se añadieron para arruinar la reputación de JavaScript los efectos de la denominada guerra de navegadores, es decir, una amarga competitividad entre Microsoft y los otros fabricantes de navegadores para hacerse con el liderazgo del mercado.

¿Y qué tiene que ver JavaScript con todo esto? Tratemos de entenderlo. En 1996, Microsoft creó, para Internet Explorer 3, el lenguaje jScript, una versión propia de JavaScript con características específicas y comportamientos distintos a los de JavaScript, lo que hizo que los sitios desarrollados con una de las dos versiones del lenguaje no fueran compatibles con todos los navegadores.

Todos estos elementos de confusión, unidos a la concepción difusa de finales de los años 90 y principios de los 2000, según la cual las aplicaciones “serias” se ejecutaban sobre servidores y no sobre el cliente (PC del usuario), provocaron que los desarrolladores profesionales adoptaran una posición muy negativa contra JavaScript, considerado solo un lenguaje para aficionados y gráficos.

Así, pues, ¿debemos considerar JavaScript como un lenguaje de serie B? Nosotros creemos que no. Vamos a ver por qué.

El renacer de JavaScript

A principios de esa década, la situación empezó a cambiar. Nacieron muchos elementos nuevos que contribuyeron a generar una consideración distinta de JavaScript por parte de la comunidad de desarrolladores. Resumimos aquí brevemente los principales.

En primer lugar, el nacimiento de Chrome (2008), impulsado por el gigante Google, produce un fuerte cambio en el mercado de los navegadores: su motor de ejecución de JavaScript (V8) incrementó hasta tal punto la velocidad de JavaScript que permitió tener aplicaciones complejas en ejecución en el navegador, es decir, sin tener que instalarlas antes en el PC. Esta posibilidad hoy en día parece más bien normal, pero hace 10 años no lo era en absoluto. Fue una gran revolución.


NOTALas estadísticas de uso de los navegadores (por ejemplo, https://www.w3counter.com/globalstats.php) indican que Chrome es el navegador más utilizado, seguido de lejos por Safari (para móvil). Internet Explorer, Opera y Firefox quedan muy por detrás.

En segundo lugar, los nuevos procesadores multicore o multinúcleo (dual, quad...) permiten una ejecución real en paralelo de los programas. Esta potencia puede ser bien explotada con técnicas “asíncronas” de programación que encuentran en JavaScript un entorno muy adecuado (encontrarás los detalles de la ejecución asíncrona en el capítulo dedicado a Ajax).

No podemos olvidarnos del nacimiento de la denominada web 2.0 que, con su fuerte integración entre los servicios ofrecidos por los distintos sitios (por ejemplo, el modo en que las redes sociales se integran entre ellas), ha impulsado la creación de aplicaciones basadas en los navegadores.

Por último, pero no menos importante, la creación de un estándar del lenguaje Java-Script aceptado por todos los fabricantes de navegadores ha llevado a una especie de “ennoblecimiento”.

La creación de un estándar, conocido como ECMAScript, fue obra de la ECMA (European Computer Manufacturers Association, conocida actualmente como ECMA International).

Esta asociación fue fundada, con sede en Ginebra, en 1961 con el deber de crear estándares para el sector informático y de las telecomunicaciones.

En 1996, Netscape confió JavaScript a ECMA con la tarea específica de crear un estándar. En 1997 nació la primera edición de ECMA-262, lo que actualmente se conoce como ECMAScript (nombre de compromiso entre las instancias sobre todo de Netscape y Microsoft).

Desde entonces se han ido sucediendo distintas versiones de ECMAScript, de las cuales JavaScript es una implementación.

Todos estos acontecimientos han determinado un renovado y creciente interés por Javascript, incluso fuera de su entorno tradicional (el web). Actualmente, de hecho, es posible crear aplicaciones stand alone en JavaScript que no necesitan un navegador. Entre estas aplicaciones destacamos:

•Aplicaciones de escritorio (que se instalan en el PC) como Visual Code, de la cual hablaremos en un apéndice y que hemos utilizado para escribir los ejemplos de este libro.

•Aplicaciones de servidor gracias a plataformas como Node.js.

•Aplicaciones móviles (tabletas y smartphones).

•Aplicaciones IoT (Internet of Things o Internet de las cosas).

Estas aplicaciones SIN navegador no forman parte de este libro, que se centrará, en cambio, en el uso de JavaScript en el entorno de los sitios de Internet y de la web.

Sin embargo, esto no quita que el uso de JavaScript fuera de la web haya contribuido a hacer crecer su fuerza y su popularidad.

La popularidad de JavaScript

En los últimos años, como hemos podido ver, JavaScript se ha convertido en un lenguaje con una importancia y una presencia significativas, en muchos ámbitos y marcos distintos.

Siempre es difícil medir la popularidad y la difusión de un lenguaje, pero los principales indicadores sitúan a JavaScript de forma estable entre los 10 primeros: por ejemplo, ocupa la primera posición en la clasificación de GitHub (https://octoverse.github.com/), la séptima en la del IEEE (https://spectrum.ieee.org/computing/software/the-2017-top-programming-languages) y la octava para TIOBE (https://www.tiobe.com/tiobe-index), etc.

Clasificaciones a parte, JavaScript es un lenguaje que vale la pena tener en cuenta para proyectos propios y, si aún necesitas más confirmaciones, te aconsejamos que visites la página http://shouldilearnjavascript.com/.

JavaScript y ECMAScript

Existen 8 versiones de ECMA-262; la publicación de nuevas versiones se produce en estos momentos anualmente, por lo que, desde la edición 6 del estándar, el nombre de la versión sigue el año de publicación, aunque se ha elegido mantener también el número de orden de las ediciones.

La última versión disponible en estos momentos es ECMAScript 2017, también conocida como ES8 por ser la octava edición del estándar. Existe una nueva versión, la ECMAScript 2018, en fase avanzada de definición.

Si consideramos el ámbito que nos interesa (el web), esta última edición es incluso demasiado nueva para contar con un buen soporte por parte de los navegadores.

Podemos decir que las versiones de referencia son la 5 y la 6 (la primera conocida también con el nombre del año, ECMAScript 2015).


NOTAEl proyecto Kangax en GitHub aporta algunas tablas que detallan el nivel de compatibilidad de los navegadores (y de aplicaciones como Node.js), en función de la edición de ECMAScript:ES5: https://kangax.github.io/compat-table/es5/ES6: https://kangax.github.io/compat-table/es6/ES2016/2017: http://kangax.github.io/compat-table/es2016plus/

A finales de 2017, los cuatro navegadores principales (Chrome, Safari, Firefox y Microsoft

Edge) cuentan con un muy buen soporte (>95 %) del ES6; es a esta versión a la que haremos referencia en este libro.

Los hermanos de JavaScript

Las críticas de los teóricos hacia JavaScript favorecieron el nacimiento de variantes de JavaScript que lo “mejoran” en los puntos considerados como más débiles.

Los programas escritos con estos lenguajes, para no perder la posibilidad de ser utilizados dentro de los navegadores, los cuales soportan solo programas escritos en Java­Script, deben ser posteriormente traducitos a JavaScript. La traducción se lleva a cabo de forma automática por medio de programas especiales denominados transpiler, que toman el programa escrito en un lenguaje y lo traducen a otro programa escrito en un lenguaje distinto.

Entre estos lenguajes variantes de JavaScript, uno de los más populares es el TypeScript de Microsoft. Angular, uno de los frameworks de JavaScript más utilizados, desde su versión 2, está escrito en TypeScript y no en JavaScript.


Cómo escribir código JavaScript

Antes de empezar a describir el potencial de JavaScript, queremos hacer una panorámica de las herramientas que pueden ser útiles para trabajar y mostrar cómo integrar los comandos de este lenguaje en las páginas HTML .

Temas tratados

•Herramientas de trabajo

•Integración de código JavaScript en páginas HTML

Empecemos por las herramientas de trabajo.

Herramientas de trabajo

Si bien, teóricamente, para escribir código JavaScript y HTML basta con disponer de un editor de textos (como el Bloc de notas) y un navegador, cuando se empieza a escribir código de un modo un poco más “serio”, las herramientas adecuadas pueden realmente marcar la diferencia.

Sin pretender ser exhaustivos, en las páginas siguientes proponemos una panorámica de las herramientas (gratuitas) más conocidas.

Editor de texto

Una primera alternativa al Bloc de notas está formada por editores de texto “más evolucionados”.

Recordemos tres de ellos:Notepad ++, Atom y Visual Studio.

El primero de ellos, Notepad ++, es un editor gratuito que puede descargarse desde el sitio https://notepad-plus-plus.org/.

Su interfaz es sencilla y de fácil uso.

Dispone de una serie de características muy útiles:

•Resaltado de la sintaxis.

•Agrupación de partes homogéneas de código (Syntax Folding) para poder ocultar o mostrar partes de un documento largo.

•Resaltado de la sintaxis y Syntax Folding personalizado por el usuario.

•Resaltado de los paréntesis.

•Búsqueda/reemplazo mediante expresiones regulares (Perl Compatible Regular Expression).

•Función Autocompletar de la sintaxis.

•Marcadores.

•Pantalla con pestañas.

•Visualización de documentos en paralelo para su comparación.

Atom es un editor gratuito que se puede descargar desde el sitio https://atom.io/ disponible para distintas plataformas (OS X, Windows y Linux). Puede ser completado con distintos paquetes de código abierto y dispone de soporte para el sistema de control de versiones Git.

Entre los puntos fuertes de Atom se encuentra:

•Función Autocompletar.

•Resaltado de la sintaxis.

•Función de búsqueda y reemplazo entre distintos archivos.

•Posibilidad de abrir varios archivos en paneles paralelos para poder compararlos.

Visual Studio Code es el editor que hemos utilizado para escribir los ejemplos de este libro. También hemos dedicado un apéndice a su instalación y configuración. Es un editor desarrollado por Microsoft para diversas plataformas (OS X, Windows y Linux). Se trata de una herramienta gratuita que se puede descargar desde la página https://code.visualstudio.com/.

Dispone de Git integrado y se puede completar con otros paquetes.

Entre sus puntos fuertes se encuentran:

•Función Autocompletar.

•Resaltado de la sintaxis.

•Función de búsqueda y reemplazo entre distintos archivos.

•Posibilidad de fijar breakpoints o puntos de interrupción.

•Trabaja directamente con archivos y carpetas sin necesidad de crear proyectos.

Linter

Un linter es un programa que por lo general se integra con un editor de código y permite resaltar los errores de sintaxis o, en general, de escritura del código.

Uno de los linter para JavaScript más conocido es ESLint (https://eslint.org/).

En el apéndice dedicado a Visual Studio Code explicaremos cómo integrar esta útil herramienta en el editor de Microsoft.

Servidores web

Muchos de los ejemplos de este libro pueden ser ejecutados desde un sistema de archivos, pero, en ciertos casos, es preciso ejecutar las pruebas del código desde un servidor web.

Puedes utilizar un servicio online o bien, y esta es la solución que te recomiendo si quieres evitar tener que transferir archivos por FTP (corres el riesgo de probar los archivos en una versión que no sea la última y crear confusión), se puede instalar un servidor web en el ordenador local. Aconsejamos XAMPP (https://www.apachefriends.org/es/index.html), a cuya instalación hemos dedicado un breve apéndice.

Integrar los comandos JavaScript en las páginas HTML

Tras haber visto la variedad de herramientas que pueden facilitar el trabajo, vamos a ver cómo hacer que convivan JavaScript y HTML.

Básicamente, contamos con dos posibles soluciones:

•Insertar el código JavaScript dentro del mismo archivo que contiene el HTML.

•Escribir el código JavaScript en un archivo externo con extensión .js y después llamar este archivo en el HTML.

Empezamos con un ejemplo del primer caso:

<!doctype html><html lang="es"><head><meta charset="utf-8"><title>Prova1</title><meta name="description" content="Prueba1"></head><body><p id="output" /><script type="text/javascript">const msgHello = 'Hola mundo';document.getElementById('output').innerHTML = msgHello;</script></body></html>

Independientemente de lo que hace este código y de su sintaxis, observa que las instrucciones de JavaScript están insertadas en la etiqueta <script> y se especifica como atributo el tipo de código contenido en la etiqueta (que es text/javascript).

Observa también que el código está escrito al final de la página, justo antes del cierre de la etiqueta <body>, de manera que el código sea llamado cuando todo el DOM del documento HTML haya sido cargado.

Esta posición del código no es obligatoria, pero sí muy recomendable para evitar problemas derivados de la no carga (temporal) de elementos a los cuales podría referirse el código.


NOTADOM, Document Object Model, es el conjunto de objetos de un documento HTML que pueden ser manipulados mediante código. Hablaremos de ello de forma detallada en un capítulo dedicado.

El segundo caso, que es más práctico si el código JavaScript es complejo y largo o si este se debe utilizar en más de un archivo, consiste en crear dos archivos distintos, el HTML y el .js, con código JavaScript y después llamar al archivo .js dentro del archivo HTML, como en el siguiente ejemplo:

<!doctype html><html lang="es"><head><meta charset="utf-8"><title>Prueba1</title><meta name="description" content="Prueba1"><!--<link rel="stylesheet" href="css/styles.css?v=1.0">--></head><body><p id="output" /><script type="text/javascript" src="https://www.litres.rucodice.js"></script></body></html>

El archivo .js es llamado mediante el atributo src de la etiqueta <script>. También en este caso, el código JavaScript es llamado al final del cuerpo del documento.

En realidad, los dos casos (archivo externo, código interno en el archivo) pueden coexistir. Podríamos decir que el archivo externo contiene código genérico que es válido para varias páginas, mientras que el interno del archivo HTML solo tiene código específico para la página o para una acción puntual. En este caso, se necesitan dos (o más) etiquetas <script>, una para llamar al archivo externo y otra, para el código gestionado de forma interna.

<script type="text/Javascript" src="https://www.litres.rufunzCookie.js"></script><script>let nombreUsuario = leerCookie('userName');if (nombreUsuario != '') {document.getElementById('saludo').innerHTML = `Hola ${nombreUsuario}`;} else {nombreUsuario = prompt('No te conozco. Escribe tu nombre:', '');if (nombreUsuario != '' && nombreUsuario != null) { configuraCookie('userName', nombreUsuario, 3);}}</script>

Advertencia

La solución más común para la escritura del código es la que prevé tener el código en un archivo externo que se llamará en el archivo HTML, pero, para facilitar el uso de los ejemplos del libro, hemos mantenido el código interno en el archivo HTML.

Así, cada archivo es “autosuficiente” y funcional, sin necesidad de muchas dependencias.


¡Hola mundo!

Cuando se aprende a programar, el primer ejemplo siempre es el de mostrar un mensaje de saludo. Nosotros también lo haremos así.

Temas tratados

•Escribir dentro de un elemento HTML

•Crear comentarios en el código

•Crear constantes y variables

•Tipos de datos

•Usar instrucciones condicionales (if)

•Crear y utilizar objetos de tipo dato

•Modificar la clase de estilo asignada a un elemento HTML

Aportamos solo la parte <body> del archivo que, evidentemente, deberá completarse con un encabezado.

<body><p id="output" ></p><script type="text/javascript">// Constante de tipo textoconst saludo = 'Hola mundo';// Busco en el DOM la etiqueta con ID = 'output' y asigno su contenidodocument.getElementById('output').innerHTML = saludo;</script></body>

Puedes encontrar este ejemplo en el archivo Holamundo .html .

Para empezar, creamos una etiqueta <p> a la cual asignamos el id “output” que después manipularemos vía código. Es importante asignar el atributo id a los elementos HTML que vamos a gestionar vía código, puesto que el valor de este atributo permite hacer referencia fácilmente al objeto en cuestión.

La parte Javascript de nuestro archivo está formada por dos líneas de código y dos líneas de comentarios. Las líneas de comentario son las que empiezan con una doble barra inclinada (//) y son líneas que no se ejecutan, sino que permiten al desarrollador insertar notas y comentarios concretos para facilitar una futura lectura o una gestión por parte de otros desarrolladores.

JavaScript también permite comentar un bloque entero de líneas, sin tener que poner necesariamente la doble barra delante de cada línea.

Para comentar en bloque un grupo de líneas, basta con poner barra asterisco (/*) al inicio de la primera línea que deseamos comentar y asterisco barra (*/) al final de la última:

/* primera línea comentadasegunda línea comentadatercera línea comentada */

Después de este paréntesis acerca de los comentarios, centrémonos en las dos líneas de código auténtico, empezando por la primera.

const saludo = 'Hola mundo';

Antes de pensar en lo que este código hace realmente, observa que las líneas de código JavaScript terminan con un punto y coma (;).

Dicho esto, vemos que en esta línea se crea una constante con el nombre saludo y se le asigna el valor ‘Hola mundo’.

La constante se crea mediante la instrucción const y es una parte de la memoria a la cual se asignan un nombre y un valor fijo que permanece inmutable durante toda la ejecución del código. Con el nombre de la constante del código se hará referencia a su valor.

Una constante puede ser utilizada varias veces en el código y, el hecho de asignarles el valor en un único punto, permite más adelante una actualización más sencilla y una gestión más fácil del valor mismo.


NOTAImagínate si hubiéramos usado la constante cinco o seis veces en el código y, después, decidiéramos cambiarle el valor. Bastará cambiar el valor a la constante para que dicho valor cambie en todo el código. Si hubiéramos utilizado directamente el valor, deberíamos modificarlo cada vez que aparece.

El nombre de una constante, o indicador, debe empezar con una letra, un guión bajo (_) o el signo del dólar ($) y puede contener caracteres alfabéticos, numéricos o guiones bajos.

Nuestra constante, concretamente, es de tipo cadena, es decir, es un texto, y se sitúa entre apóstrofes o comillas simples.

Ya anticipamos que, además del tipo cadena, una constante puede tener valores de otros tipos. Concretamente:

•booleano: es decir, un valor como verdadero/falso - true/false.

•null: un valor nulo.

•undefined: un valor no definido (la constante existe, tiene un nombre pero no un valor; a decir verdad, no es demasiado útil).

•number: un número sobre el cual se pueden realizar operaciones matemáticas.

•cadena: un conjunto de caracteres alfanuméricos.

•symbol: (nuevo en ECMAScript 2015): un tipo que se utiliza para identificar propiedades concretas dentro de los objetos (no te preocupes si no entiendes esta definición, pues todo quedará más claro cuando presentemos el concepto de objeto).

En el transcurso de este libro, tendremos la ocasión de profundizar en el tema de los tipos de datos. Sin embargo, debemos advertir de que JavaScript, a diferencia de otros lenguajes, no necesita que el tipo de constante (o de la variable, como veremos más adelante) sea declarado explícitamente. JavaScript intenta identificar el tipo de valor que se asigna.

Después de esta digresión sobre los tipos, volvamos a nuestro código y, en concreto, a la segunda línea a analizar:

document.getElementById('output').innerHTML = saludo;

El objeto document representa todo el documento HTML, del cual, mediante la función getElementById, seleccionamos el elementos con el id output.

Una vez seleccionado el objeto, que recordemos que es un elemento <p>, cambiamos su contenido HTML mediante la propiedad innerHTML: así, mostramos en su interior el contenido de la constante saludo.

Un poco de dinamismo

Así como está, el código que hemos escrito no sirve para mucho: habría sido mucho más rápido escribir directamente nuestro mensaje en el código HTML.

Las cosas cambian si queremos mostrar un mensaje distinto según el momento del día.

Muestro solo la parte JavaScript del código, puesto que la parte HTML se mantiene igual.

<script type="text/javascript">// hora del sistemaconst hora = new Date().getHours();let mensaje;if (hora < 13) mensaje = 'buenos días';else if (hora < 21) mensaje = 'buenas tardes';else if (hora < 24) mensaje = 'buenas noches';// Busco en el DOM la etiqueta con el ID = 'output' y le asigno el contenidodocument.getElementById('output').innerHTML = mensaje;</script>

Puedes encontrar este ejemplo en el archivo Holamundodinamico .html

Este código contiene varias novedades: analicémoslas una a una.

Empecemos por el valor de la constante hora.

const hora = new Date().getHours();

Mediante la instrucción new Date() se construye un nuevo objeto de tipo fecha. Como no especifica la fecha que el objeto debe contener entre los paréntesis, el objeto fecha contiene la fecha y la hora del sistema y, por tanto, la fecha y la hora en que se ejecuta el comando.


NOTAExisten tres posibilidades para asignar a un objeto del tipo fecha una fecha determinada:•new Date(milisegundos): la fecha se especifica como el número de milisegundos transcurridos desde el 1 de enero de 1970, que es la fecha 0.•new Date(fecha como cadena): la fecha se expresa como una cadena que utiliza el sistema de notación americano con eventuales nombres de los meses escritos en inglés (new Date("september 05, 2018 11:43:00")) o usando el formato mes día año (new Date("09/05/2018")). Ambas fechas de los ejemplos propuestos indican el 5 de septiembre de 2018.•new Date(año, mes, día, hora, minutos, segundos, milisegundos): la fecha se crea especificando año, mes, día... No es necesario especificar todos los valores si no son necesarios. Ten en cuenta que el mes se expresa con un número que va del 0 al 11. new Date(2018,08,05) crea la fecha 5/9/2018.

Una vez se ha creado el objeto fecha, con la función getHours() recuperamos la hora memorizada en la fecha. La hora se representa con un número del 0 al 23.


NOTAExisten diferentes funciones que permiten extraer partes de la fecha/hora almacenada en un objeto fecha:•getDate(): devuelve el día del mes con un número del 1 al 31;•getDay(): devuelve el número del día de la semana con un valor del 0 (domingo) al 6 (sábado);•getFullYear(): devuelve el año con un número de cuatro cifras;•getMilliseconds(): devuelve los milisegundos con un número del 0 al 9999;•getMinutes(): devuelve los minutos con un número del 0 al 59;•getMonth(): devuelve el mes con un número del 0 al 11;•getSeconds(): devuelve los segundos con un número del 0 al 59;•getTime(): devuelve el número de milisegundos transcurridos desde la media noche del 1 de enero de 1970;•getTimezoneOffset(): devuelve la diferencia entre el UTC (Coordinated Uni- versal Time: es la zona horaria de referencia a partir de la cual se calculan el resto de zonas horarias del mundo) y la hora local expresada en minutos. La función en Italia devuelve ¬60 con la hora solar y ¬120 con la hora legal.Para las funciones que acabamos de ver, existen los correspondientes UTC (getUTCDate(), getUTCDay(), getUTCFullYear(), getUTCHours(), getUTCMilliseconds(), getUTCMinutes(), getUTCMonth() y getUTCSeconds()) que se comportan exactamente como los anteriores, pero hacen referencia al UTC.

Una vez hemos recuperado la hora, podemos recurrir a instrucciones condicionales (if) para decidir qué mensaje mostrar.

Antes de explicar la sintaxis de la instrucción condicional, debemos indicar que el mensaje queda almacenado en una variable denominada precisamente mensaje. La variable, como las constantes, es una porción de memoria a la cual se puede asignar un valor. A diferencia del valor de la constante, el valor de una variable, como la misma palabra indica, puede cambiar durante la ejecución del código.

let mensaje;

Una variable se declara con la palabra clave let y las reglas para su denominación son las mismas que hemos visto para los nombres de las constantes.

Ahora que disponemos de nuestra variable, podemos utilizarla para almacenar el mensaje que queremos mostrar dentro del párrafo con el id output.

El mensaje variará según la hora, es decir, si se verifica una determinada condición; por ejemplo, para que el mensaje sea ‘buenos días’, la hora debe ser un número menor que 13.

Para efectuar este tipo de verificación, debemos recurrir a las instrucciones condicionales.

En su forma más simple, una instrucción condicional tiene esta forma:

if (condición a verificar) acción a ejecutar si se verifica la condición

Esta es la forma de nuestra primera instrucción condicional:

if (hora < 13) mensaje = 'buenos días';

La condición que se debe comprobar es que la constante hora tenga un valor menor que 13. Si la condición se verifica, la variable mensaje asume el valor ‘buenos días’.

¿Y si la condición no se verifica?

En este caso en concreto, se realizan otras dos comprobaciones con las instrucciones else if.

else if (hora < 21) mensaje = 'buenas tardes';else if (hora < 24) mensaje = 'buenas noches';

Si hora es un número menor que 21, mensaje asume el valor ‘buenas tardes’ y si hora es un número menor que 24, mensaje asume el valor ‘buena noches’.

Si ninguna de estas condiciones alternativas se verifica, entonces (instrucción else), mensaje asume el valor ‘hola’.

else mensaje = 'hola';

Las instrucciones else if y else son opcionales y se podría limitar a especificar una acción si se verifica una única condición mediante una simple instrucción if.

En nuestro ejemplo, hemos utilizado una forma “abreviada” de las instrucciones if agrupando en una sola línea tanto la condición a verificar como la acción a cumplir si la condición se verifica.

Y hemos podido hacerlo porque la acción que se debe llevar a cabo es una.

Podríamos haber adoptado la forma más amplia:

if (hora < 13) {mensaje = 'buenos días';} else if (hora < 21) {mensaje = 'buena tardes';} else if (hora < 22) {mensaje = 'buenas noches';} else {mensaje = 'hola';}

En esta forma, la acción que se debe llevar a cabo está encerrada entre llaves.

Este sistema de notación es obligatorio si las acciones a ejecutar en el caso en que se verifique una condición son más de una.

Observa el ejemplo siguiente:

<head><style type="text/css">.mañana { background-color: #A0EEF0; color: #971D78;}.tarde { background-color: #47B8FE; color: #DCFE24;} .noche { background-color: #FA8F6F; color: #971D78;}.madrugada { background-color: #0A0D2C; color: #FFFFFF;}</style></head><body class="mañana"><p id="output"></p><script type="text/javascript">// hora del sistema const hora = new Date().getHours(); let mensaje; let nombreEstilo;if (hora < 13) {mensaje = 'buenos días'; nombreEstilo = 'mañana';} else if (hora < 21) {mensaje = 'buenas tardes';nombreEstilo = 'tarde';} else if (hora < 24) {mensaje = 'buenas noches';nombreEstilo = 'noche';} else {mensaje = 'hola';nombreEstilo = 'madrugada';}document.getElementById('output').innerHTML = mensaje; document.body.className = nombreEstilo;</script></body>

Puedes encontrar este ejemplo en el archivo Holamundodinamico2 .html

Hemos añadido a nuestro archivo una parte de clases CSS. Según el horario que sea, asignamos también un valor a la variable nombreEstilo. Esta variable se utilizará para asignar esa clase específica al elemento <body> en nuestra página y, concretamente, cambiar su color de fondo y el color del texto insertado.


Trabajar con cadenas

ECMAScript nos permite trabajar con cadenas de un modo muy interesante. En este capítulo, queremos explorar algunas posibilidades en las que profundizaremos más adelante.

Temas tratados

•Operador booleano or ||

•Operador booleano and &&

•Cargar una imagen trabajando con la propiedad src de un elemento IMG

•Operador de concatenación +

•Operadores de igualdad == y ===

•Plantillas de cadena

Como primer ejemplo, queremos comprobar el día de la semana (recuerda que con la función getDay de un objeto fecha podemos obtener un número que corresponde al día de la semana) y mostrar en la página HTML una carita correspondiente al día.

En nuestro sitio web encontrarás siete imágenes (Figura 4.1) cuyo nombre está formado por la palabra "carita" y un número que corresponde al día de la semana al cual se refiere la figura. Recuerda que el número 0 corresponde al domingo y el 6, al sábado. Son imágenes de tipo .png.


Figura 4.1 – Las caritas que se utilizarán en este ejercicio.

Para cargar la imagen correcta, tras haber adivinado el número correspondiente al día de la semana, escribiremos el nombre de la imagen y pasaremos vía código este nombre a la propiedad src del objeto imagen.

Para simplificar, almacenamos el archivo HTML en la misma carpeta que las imágenes, aunque nada nos impide escribir el nombre de la imagen que se cargará con la ruta correcta para llegar a ella.

<body><p id="output" ></p><img id="carita" /><script type="text/javascript"> const dia = new Date().getDay(); const valorSrc ='Carita' + dia + '.png'; document.getElementById('carita').src = valoreSrc; </script></body>

Puedes encontrar este ejemplo en el archivo Carita .html

Mostramos toda la parte <body> del archivo HTML, puesto que hemos añadido una etiqueta <img>. La etiqueta tiene un atributo id, de manera que posteriormente sea posible llegar a ella a través del código. En cambio, falta el atributo src que se añadirá vía código.

Pasemos ahora a la parte JavaScript de este archivo. En primer lugar (const dia = new Date().getDay();), almacenamos en la constante dia el número del día de la semana de la fecha del sistema, después, creamos la constante valorSrc y le asignamos como valor el resultado de la escritura de la palabra “Carita” con el número del día, seguido de la extensión ".png”.

const valorSrc ='Carita' + dia + '.png';

Para crear el nombre de la imagen, hemos utilizado el operador de concatenación +, que permite unir las cadenas entre ellas.

De este modo, tenemos exactamente el valor para el atributo src de nuestra imagen: cada día, cargaremos una imagen distinta.

document.getElementById('carita').src = valorSrc;

La técnica que hemos visto para escribir las cadenas funciona perfectamente y se utiliza en casi todos los lenguajes de programación, pero ECMAScript 6 introdujo otra técnica muy interesante que se basa en plantillas de cadena (o template litterals, en inglés).

En lugar de usar la instrucción:

const valorSrc ='Carita' + dia + '.png';

podríamos haber escrito

const valorSrc = `Carita${dia}.png`;

El resultado habría sido idéntico, pero habríamos utilizado una plantilla de cadena.

Lo primero que debemos observar en las plantillas de cadena es que no están encerradas entre comillas como las cadenas normales, sino entre el carácter backtick (` `) o acento grave. Este carácter se obtiene pulsando la tecla situada a la derecha de la tecla P.


NOTAResulta muy incómodo escribir el carácter backtick en los ordenadores portátiles que no tienen teclado numérico. En la sección Insertar el backtick o acento grave, al final de este capítulo, proponemos algunas soluciones para ello.

Las plantillas de cadena pueden contener marcadores. Estos se indican con el signo del dólar y entre llaves (${expresión}). Durante la ejecución, el marcador queda sustituido con el valor de la expresión que contiene. En nuestro caso, está sustituido por el valor de la constante dia.

Un aspecto interesante de las plantillas de cadena es que dentro del marcador las expresiones se ejecutan y, por lo tanto, se pueden llevar a cabo, por ejemplo, operaciones matemáticas.

Añade al código propuesto anteriormente las líneas siguientes:

let mensaje;mensaje = `Faltan ${6 - dia} días para el fin de semana`……document.getElementById('output').innerHTML = mensaje;

Nuestra variable mensaje contiene una plantilla de cadena. En su interior, hay un marcador en el cual se ejecuta una operación matemática. El resultado de esta operación será sustituido por el marcador.

Dentro de las plantillas de cadena, también es posible insertar código HTML. Podríamos modificar nuestro ejemplo de la siguiente manera:

mensaje = `Faltan <strong> ${6 - dia} </strong> días para el fin de semana`

Podríamos complicar un poco nuestro ejemplo mostrando un mensaje distinto si el día en que nos encontramos es sábado o domingo (de hecho, no tiene demasiado sentido que en estos días se muestren los días que faltan para el fin de semana).

Así, pues, podríamos sustituir la línea de código anterior con la instrucción if siguiente:

if (dia === 0 || dia === 6) mensaje = 'Buen fin de semana'else mensaje = `Faltan ${6 - dia} días para el fin de semana`

Puedes encontrar este ejemplo en el archivo caritaMensaje .html

La parte else de este códido es absolutamente clara: centrémonos en la parte if, que contiene muchas novedades.

En primer lugar, encontramos el nuevo operador === que verifica la igualdad entre el valor de la variable dia y los números 0 o 6.

El operador === os puede sorprender un poco, y existe también en JavaScript el operador ==, aunque la verificación de igualdad es menos estricta.

La Tabla 4.1 resume el significado de los distintos operadores que utilizan el símbolo =.

Otra novedad de este código consiste en el hecho de que la instrucción condicional, de hecho, verifica dos condiciones: que dia sea igual a 0 o que sea igual a 6 (es decir, que sea domingo o sábado).

Las dos comparaciones están unidas por el operador ||, que indica un or booleano, es decir, la condición en su conjunto es verdadera si como mínimo una de las dos (o más) condiciones unidas por el operador || es verdadera.


NOTAPara obtener el operador || hay que teclear dos veces el carácter |, que se encuentra en la tecla 1 del teclado alfanumérico. Para obtenerlo, debes pulsar la combinación AltGr + 1.

Si se desea que las condiciones en su conjunto sean verdaderas cuanto todas las condiciones especificadas son verdaderas, hay que unirlas con el operador &&, que indica un and booleano. Obviamente, en este caso específico, el uso de && no tendría ningún sentido porque la variable dia no puede tener el valor 0 y 6 simultáneamente. Su valor puede ser o 0 o 6.

Tabla 4.1 – Operadores.


OperadorSignificadoEjemplo
=Asigna un valor a una variable o a una constanteconst hora = 5Declara la constante hora y le asigna como valor el número 5
==Operador de igualdad. Verifica la igualdad entre las expresions a su derecha y a su izquierda. Las expresiones deben ser iguales en el valor pero no necesariamente en el tipohora == "5"Verifica si hora es igual a la cadena “5”.Esta expresión devuelve Verdadero porque los valores son iguales incluso si los tipos son distintos (en realidad, hora es un número)
===Operador comparativo. Verifica la igualdad entre las expresiones a su derecha y a su izquierda. Las expresiones deben ser iguales tanto en el valor como en el tipohora === "5"hora === 5La primera expresión es falsa, porque los tipos son distintos, mientras que la segunda es verdadera porque los tipos son iguales

Cadenas multilínea

Otro aspecto interesante de las plantillas de cadena es que se pueden crear fácilmente cadenas multilínea sin necesidad de recorrer a otros operadores.

Para evitar que la cadena multilínea se refleje en el HTML en una única línea, necesitamos un bloque de código <pre>.

Así, añadimos a la parte del HTML de nuestro archivo la línea siguiente:

<pre id="output1"></pre>

Después, en la parte de JavaScript, agregamos este código:

const mensaje1 = `dime¿qué tienes programado para hoy?`……document.getElementById('output1').innerHTML = mensaje1;

Puedes encontrar este ejemplo en el archivo CaritaMensajeInicio .html

La Figura 4.2 muestra la salida de este fragmento en un navegador.


Figura 4.2 – La cadena multilínea en el navegador.

Muy a menudo se recurre a las cadenas multilínea para crear un código HTML con formato.

Para hacer una prueba, sustituye la etiqueta <pre> por una etiqueta <div> que podremos rellenar después con otros objetos HTML:

<div id="output1"></div>

Ahora, corrige también el valor de la constante mensaje1:

const mensaje1 = `<h1>hola</h1><p>¿qué tienes programado para hoy?</p>`

Puedes encontrar este ejemplo en el archivo CaritaMensajeInicioHTML .html

Ya no necesitamos realizar más cambios. Prueba el archivo en un navegador y muestra la estructura (pulsando F12 en el teclado, en la mayoría de los navegadores) o el código fuente de la página (Figura 4.3).

Observa que en la etiqueta <div> el código HTML que hemos insertado permanece distribuido de forma ordenada en varias líneas.


Figura 4.3 – La estructura de la página en el navegador.

Insertar el backtick o acento grave

Para insertar el carácter backtick con el teclado italiano, hay que pulsar la combinación de teclas ALT + 96 desde el teclado numérico.

Esto es un problema con los PC portátiles, muchos de los cuales no disponen de teclado numérico (algunos cuentan con teclas que corresponden al teclado numérico pulsando a la vez la tecla fn, pero no es lo habitual).

Por esta razón, vamos a ver cómo podemos obtener este caracter. Te proponemos dos soluciones: el mapa de caracteres y el teclado italiano 142.

La solución más inmediata, aunque quizás poco práctica, es la que implica el uso del mapa de caracteres, desde el cual podemos copiar el carácter que necesitamos (Figura 4.4).

Para abrir el mapa de caracteres, en Windows 7, selecciona Inicio > Todos los programas > Accesorios > Herramientas del sistema > Mapa de caracteres o, en Windows 10, Inicio > Todas las aplicaciones > Accesorios de Windows > Mapa de caracteres.

Otras solución, que, para nosotros, es más cómoda si se debe utilizar el backtick con frecuencia, consiste en utilizar el teclado italiano de 142 caracteres, que sería el teclado italiano para programadores.


Figura 4.4 – Backtick en el mapa de caracteres.

Para activarlo, debemos acceder a la sección Reloj, idioma y región del panel de control. (Figura 4.5).


Figura 4.5 – La sección Reloj, idioma y región del panel de control.

Para abrir esta ventana, con Windows 7 selecciona Inicio > Panel de control > Reloj, idioma y región, y con Windows 10 selecciona Inicio > Sistema de Windows > Panel de control > Hora e idioma > Región e idioma > Opciones adicionales de fecha, hora y configuración regional.

En esta ventana, selecciona Cambiar métodos de entrada y, después, en la ventana siguiente, haz clic sobre Opciones correspondiente al idioma italiano.

En la nueva ventana, haz clic en Agregar un método de entrada (Figura 4.6). En la ventana siguiente, localiza el teclado Querty Italiano 142 y haz clic en Añadir.


Figura 4.6 – Elige un nuevo método de entrada para el idioma italiano.

Una vez añadido el teclado, cierra las ventanas del panel de control y, en la barra de aplicaciones, localiza el icono del teclado actual: para el teclado italiano, aparecerá el icono IT. Pulsa sobre él y elige el teclado italiano 142 (Figura 4.7).


Figura 4.7 – Activar el teclado italiano 142.

A partir de ahora, para insertar el backtick, sencillamente deberás utilizar la combinación de teclas AltGr + ù.

Si has elegido insertar el teclado italiano 142, ten en cuenta que las combinaciones de teclas para la tecla Alt Gr se volverán a asignar.

Las nuevas combinaciones son las siguientes:

AltGr + Q = @

AltGr + 3 = #

AltGr + 5 = ¤

AltGr + 8 = [

AltGr + 9 = ]

AltGr + 7 = {

AltGr + 0 = }

AltGr + + = ~


Los bucles

En muchas situaciones, es necesario repetir la misma operación sobre distintos datos y, para ello, nos pueden ayudar los bucles. Existen distintos tipos de bucle: aquí estudiaremos el bucle for con índice. También veremos cómo utilizar la consola del navegador para el análisis del código.

Temas tratados

•Bucle for con índice

•Seleccionar elementos en el DOM (HTML) con los selectores CSS

•Modificar atributos de elementos en el DOM

•Utilizar el operador de asignación compuesta

•Utilizar el operador de autoincremento

•Utilizar la consola del navegador

Empezamos con un caso sencillo sobre el cual trabajaremos utilizando bucles.

Nuestro objetivo es contabilizar los elementos de una lista.

<body><ul id="numeros"><li>uno</li><li>dos</li><li>tres</li></ul><p id="output"></p><script type="text/Javascript"> const listaLI = document.querySelectorAll('#numeros li'); const mensaje = `Hay ${listaLI.length} elementos en la lista UL "numeros"`; document.getElementById('output').innerHTML = mensaje;</script></body>

Puedes encontrar este ejemplo en el archivo bucle1 .html

La parte HTML de este archivo contiene una lista no numerada (etiqueta <UL>) de elementos (etiqueta <LI>). El elenco tiene un ID asociado con valor "numeros".

La primera operación que debemos llevar a cabo en nuestro código consiste en localizar esta lista dentro de la página HTML. Para ello, utilizaremos las funciones del DOM (Document Object Model) que ya hemos utilizado en los capítulos anteriores mediante el objeto document.

Recordemos que, para encontrar un elemento HTML (una etiqueta), se pueden utilizar diferentes opciones (en el capítulo dedicado al DOM retomaremos este argumento):

•Selector CSS .miClase: busca los elementos que tienen la clase CSS denominada miClase.

•Selector CSS #miId: busca los elementos que tienen un atributo id igual a “miId”;

•tag: busca los elementos de tipo etiqueta (p, pre, ul...).

En nuestro caso específico, podemos localizar los elementos LI contenidos en el elemento UL con id="numeros" con el selector CSS "#numeros li” utilizado como argumento de la función querySelectorAll() del objeto document. La función devuelve una lista de los objetos del documento que corresponden a los selectores especificados como argumentos.

const listaLI = document.querySelectorAll('#numeros li');

El objeto listaLI (de tipo NodeList, un contenedor de objetos del cual hablaremos más adelante en este libro) contiene todos los elementos localizados con el selector pasado a la función querySelectorAll del objeto document.


NOTAEs muy habitual buscar elementos en la página mediante librerías JavaScript, entre las cuales la más famosa es jQuery, puesto que inicialmente esta operación, realizada directamente en JavaScript, era un poco compleja. Sin embargo, con el paso de los años, los navegadores han introducido nuevas funcionalidades (como, precisamente, nuestra función querySelectorAll), que en muchos casos hacen que adoptar una librería externa no valga en absoluto la pena.

A continuación, podemos utilizar listaLI para mostrar cuántos elementos hay en la lista (tres, en nuestro caso) recurriendo a la propiedad length del objeto listaLI, que precisamente contiene el número de elementos que contiene el objeto.

const mensaje = `Hay ${listaLI.length} elementos en la lista UL "numeros"`;document.getElementById('output').innerHTML = mensaje`;

Ahora, vamos a tratar de complicar un poco nuestro ejemplo. En lugar de limitarnos a contabilizar cuántos son los elementos de la lista, también queremos asociar a los elementos LI de esta lista un atributo “value”, cuyo valor expresa el número en cifras.

En otras palabras, queremos obtener un resultado como el que ves a continuación:

<ul id="numeros"><li value="1">uno</li><li value="2">dos</li><li value="3">tres</li></ul>


NOTANaturalmente, debemos pensar que tenemos que realizar esta operación de manera dinámica, por ejemplo, porque no podemos modificar nosotros el archivo HTML (creado por otro desarrollador) o porque la misma lista UL ha sido creada dinámicamente.


NOTAPara no complicar demasiado el ejercicio, supongamos que los elementos LI están definidos por orden (“uno”, “dos”...) y que, por tanto, no necesitamos saber que la palabra “dos” indica el número 2, sino que asumiremos simplemente que el primer elemento es 1, el segundo es 2, etc.

Esto significa que debemos repetir la operación de agregar los atributos value varias veces, una para cada elemento de la lista. Para ejecutar estas operaciones, recurrimos a uno de los muchos bucles que JavaScript pone a nuestra disposición: el bucle for con índice.

Su forma es la siguiente:

for (valor índice inicial; valor máximo del índice; cuánto aumenta el índice) {instrucciones a repetir}

Por ejemplo, el bucle:

for (let i=1; i <= 10; i+=1) {instruccion(i); }

repite la instrucción 10 veces, con la variable índice i, que asume valores del 1 (i=1) al 10 (i <= 10), con paso 1 (i += 1): 1, 2, 3 hasta 10. Cuando i llega a 11, el bucle termina y la ejecución continúa desde la línea siguiente.


NOTAEs habitual asignar un nombre corto, como i, j, k, a las variables índice de los bucles.

En nuestro ejemplo, hemos utilizado el operador de asignación compuesta, que combina un operador aritmético (+, en este caso) con el operador de asignación (=).

Con este operador, conseguimos realizar rápidamente 5 de i, añade 1 y asigna el resultado a i”.

La notación:

i+=1

corresponde a:

i = i+1

El operador de asignación compuesta proporciona una solución más sintética y con menos probabilidades de error, dado que no se debe repetir el nombre de la variable sobre la que se trabaja.

Una alternativa a este operador es el operador de autoincremento (i++), que desarrolla la misma función.

La diferencia principal entre el operador de asignación compuesta (i+=1) y el operador de autoincremento (i++) consiste en el hecho que el primero permite incrementos de distintas unidades (i+=2, por ejemplo), mientras que el segundo permite solo incrementos de una unidad.

Volviendo a nuestro problema, podemos añadir al código mostrado anteriormente el bucle siguiente:

for (let i=0; i < listaLI.length; i+=1) {listaLI.item(i).value = i+1;}

Puedes encontrar este ejemplo en el archivo bucles2 .html

Analicemos con detalle este código.

El bucle empieza por el número 0 y acaba antes del 3 (el valor de listaLI.length), es decir, el bucle se ejecuta 3 veces (cuando i=0, cuando i=1 y cuando i=2) y se interrumpe cuando i=3 (i < listaLI.length).

La instrucción contenida en el bucle for (es decir, que se repite en cada iteración del bucle):

listaLI.item(i).value = i+1;

utiliza el conjunto de valores item que representa el conjunto de elementos LI que se encuentran en nuestra lista UL.

Cada elemento (es decir, cada elemento LI) tiene una posición determinada en el conjunto. Podemos acceder a un elemento en concreto indicando entre los paréntesis de item un número que representa su posición.

En la primera ejecución del bucle, accedo al elemento en la posición 0 (i al inicio vale 0), en la segunda repetición, accedo al elemento en la posición 1 (i ha aumentado una unidad), en la tercera y última, accedo al elemento en la posición 2 (i ha aumentado otra unidad).

En nuestro caso específico:

•En la primera vuelta del bucle for, i = 0 y listaLI.item(i) indica el elemento LI “uno”.

•En la vuelta siguiente, i = 1 y listaLI.item(i) indica el elemento LI “dos”.

•En la tercera y última vuelta, i = 2 y listaLI.item(i) indica el elemento LI “tres”.

Observa que en JavaScript los conjuntos de valores (como listaLI) siempre tienen índices que empiezan desde 0: el primer elemento tiene índice (posición) 0, el segundo tiene índice 1 y así sucesivamente.

Ahora que ya hemos visto cómo acceder a los distintos elementos LI, debemos precisar que con listaLI.item(i).value accedemos al atributo value del elemento LI: si el atributo value ya no existe, se crea y se le asigna un valor, si no, solo se modifica el valor.

Con la instrucción listaLI.item(i).value = i+1 fijamos el valor de value al valor del índice aumentado en una unidad (para compensar el hecho de que el índice empieza desde 0 mientras que los números de la lista lo hacen desde 1).

Seguramente has observado que, en este caso, hemos escrito i + 1 y no i+=1 o i+. Esto es así porque no estamos modificando el valor de i, sino que solo lo estamos utilizando (leyendo) y, de hecho, es la instrucción for la que se ocupa de gestionar el incremento de la variable índice en cada vuelta o bucle.

La consola

Sin embargo, si ejecutamos en el navegador este código, no percibimos su acción (estamos actuando a nivel de código HTML con una modificación que no tiene ningún impacto sobre el output de la página en el navegador).

¿Y cómo podemos ver el resultado de nuestro bucle for?

Una posibilidad consiste en leer el código fuente de la página del navegador. Para acceder al código fuente de la página, pulsa con el botón derecho del ratón en cualquier punto de la página y selecciona la opción “Ver código fuente” o similar (depende del navegador): ¡verás que el código HTML ha sido modificado por nuestro código JavaScript!

Una manera más potente de analizar una página es abrir el modo de desarrolladores pulsando la tecla F12 del teclado (en Firefox y Chrome, también mediante la combinación CTRL+MAYÚS+i).

En función del navegador que se utilice, aparece una ventana independiente o una sección en la página que muestra distintas pestañas, una de las cuales permite analizar el código HTML (Figura 5.1), además de los estilos CSS y el código JavaScript cargados por la página.


Figura 5.1 – El código HTML que genera la página mostrada.

Otra sección muy interesante de las herramientas para los desarrolladores es la consola: un área donde el navegador muestra eventuales errores encontrados durante la carga de la página y/o la ejecución del código JavaScript.

Desde nuestro código, es posible utilizar la consola del navegador para escribir mensajes que nos pueden ayudar a identificar problemas (los denominados mensajes de depuración).

Por ejemplo, podemos modificar nuestro bucle for del siguiente modo.

for (let i=0; i<listaLI.length; i+=1) {console.log(`i=${i} value=${i + 1} elemento=${listaLI.item(i)}`);listaLI.item(i).value = i+1;}

Puedes encontrar este ejemplo en el archivo Bucles2 .html

La instrucción console.log llama a la función log del objeto console, que escribe un mensaje en la consola del navegador.


NOTAObviamente, si la consola no está abierta, el mensaje no aparece.

Si ejecutamos el bucle, tendremos, en la consola (Figura 5.2), líneas como estas:

i=0 value=1 elemento=[object HTMLLIElement]

i=1 value=2 elemento=[object HTMLLIElement]

i=2 value=3 elemento=[object HTMLLIElement]


Figura 5.2 – Mensajes en la consola.

Estos mensajes confirman los valores de la variable índice i, del valor calculado para el atributo value y del hecho que listaLI.item contiene objetos JavaScript que representan elementos LI.

Algunos desarrolladores suelen mostrar en pantalla estos mensajes mediante ventanas alert que se abren en la página del navegador (Figura 5.3).

alert(`i=${i} value=${i + 1} elemento=${listaLI.item(i)}`);


Figura 5.3 – La ventana alert.

Es preferible utilizar console.log en lugar de las ventanas de alert, porque console.log no interrumpe la ejecución del código y en cambio alert, sí.


Funciones

En este capítulo hablaremos de funciones que permiten agrupar varias líneas de código para mantener el orden y reutilizar más fácilmente partes de código.

Temas tratados

•Definir y utilizar funciones

•Utilizar el operador ternario

•Pasar parámetros

•Arrays

•Funciones anónimas

•Área de validez de constantes y variables

Una función es un grupo de instrucciones que ejecuta una tarea o calcula un valor.

Para trabajar con funciones se precisan dos pasos:

•declarar la función y definir sus acciones

•llamar a la función en uno o varios puntos del código

Para explicar mejor el uso de funciones, empezaremos con un ejemplo:

<body><p id="output"></p><img id="carita" /><script type="text/javascript">function esFinDeSemana() {const dia = new Date().getDay();if (dia === 0 || dia === 6) return true;else return false}let valorSrc;if (esFinDeSemana() === true) valorSrc = 'CaritaFeliz.png';else valorSrc = 'CaritaTriste.png';document.getElementById('carita').src = valorSrc;</script></body>

Puedes encontrar este ejemplo en el archivo Funciones .html

Empezamos el análisis de este código precisamente por la función esFinDeSemana:

function esFinDeSemana() {const dia = new Date().getDay();if (dia === 0 || dia === 6) return true;else return false}

Observa que, para crear la función, se utiliza la palabra function seguida del nombre de la misma función y, a su vez, seguida de un par de paréntesis.

Todas las líneas de código que forman parte de la función se sitúan entre llaves.

Anteriormente hemos dicho que una función puede limitarse a ejecutar acciones, o bien puede devolver un valor, como la función que estamos analizando.

El valor devuelto se introduce con la palabra return.

La función utiliza un código que ya te debería ser familiar: tras haber leído el número del día de la semana, si es sábado (6) o domingo (0), la función devuelve true y, si no, devuelve false (es decir, un valor booleano).

En realidad, podríamos escribir la función evitando la instrucción if y utilizando una notación más resumida:

return dia === 0 || dia === 6;

Esta instrucción devuelve el resultado de la comparación dia === 0 || dia === 6, es decir, verdadero o falso, igual que la instrucción if que hemos escrito inicialmente.

Tanto si utilizamos una instrucción if, como si recurrimos a la forma más resumida, el valor que devuelve la función se utilizará posteriormente en una instrucción if para crear el nombre de la imagen que se desea cargar en el objeto <img> con el id = carita.

if (esFinDeSemana() === true) valorSrc = ‘CaritaFeliz.png’;else valorSrc = ‘CaritaTriste.png’;

Observa que el nombre de la función se debe llamar completo entre paréntesis.

En este ejemplo, para simplificar un poco la lectura, hemos ejecutado explícitamente la comparación esFinDeSemana() === true; sin embargo, normalmente, cuando la parte derecha de la comparación es un valor booleano, no se ejecuta la comparación de manera explícita, sino que basta con una notación más reducida:

if (esFinDeSemana()) valorSrc = 'CaritaFeliz.png';

Antes de continuar, queremos mostrarte un modo más sintético de escribir una instrucción if, una manera que se puede utilizar cuando se tiene una comparación booleana y, por tanto, una única expresión a valorar si la comparación es verdadera y una única expresión a valorar si es falsa.

Las expresiones en cuestión no pueden llevar a cabo una operación, solo devolver un valor.

Toda la instrucción if anterior puede ser escrita del modo siguiente:

const valorSrc = esFinDeSemana() ? 'CaritaFeliz.png' : 'CaritaTriste.png';

Esta notación se denomina habitualmente operador ternario porque se compone de tres partes:

test booleano ? valor si verdadero : valor si falso

El resultado de un operador ternario, que siempre es un valor, se asigna a una variable o a una constante (o se utiliza para ejecutar operaciones que todavía no hemos explicado), si no, se pierde. Nuestra función se utiliza una sola vez, pero nada nos impide utilizarla también en otras situaciones.

Por ejemplo, podríamos enriquecer nuestro código como se indica a continuación, para mostrar, además de una imagen, también un mensaje adecuado para el momento de la semana:

const valorSrc = esFinDeSemana() ? 'CaritaFeliz.png' : 'CaritaTriste.png';const mensaje = esFinDeSemana() ? 'Diviértete' : 'Venga, que ya falta poco';document.getElementById('carita').src = valorSrc;document.getElementById('output').innerHTML = mensaje;

Puedes encontrar este ejemplo en el archivo Funciones1 .html

Tratemos de complicar un poco nuestro ejemplo de uso de una función haciendo que nos muestre el nombre del día de la semana actual.

<script type="text/javascript">const dia = new Date().getDay();function esFinDeSemana() {return dia === 0 || dia === 6;}function queDia() {const nombreDia = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];return nombreDia[dia];}const valorSrc = esFinDeSemana() ? ‘CaritaFeliz.png’ : ‘CaritaTriste.png’;document.getElementById('carita').src = valorSrc;document.getElementById('output').innerHTML = queDia();</script>

Puedes encontrar este ejemplo en el archivo FuncionesArray .html

La auténtica novedad de este código es la línea:

const nombreDia = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];

La constante nombreDia, a diferencia de las que hemos visto hasta hora, contiene un conjunto de datos.

Se define como array y contiene múltiples valores ordenados y colocados entre corchetes.

Dado que los valores de un array están dispuestos en un orden determinado, es posible acceder a él especificando su posición mediante un número de índice que empieza desde 0 (el primer elemento del array tiene el valor 0).

Para acceder a un elemento de un array, basta con poner entre los corchetes de dicho array el número de índice del elemento.

nombreDia[2]

devolverá el valor “Martes” que se encuentra en la posición 2 en el array (0 corresponde a domingo; 1, a lunes; 2, a martes... y 6, a sábado).

Nuestro array contiene los nombres de los días de manera que su posición corresponda al valor devuelto por getDay() y almacenado en la variable dia, que después podemos utilizar como índice de nuestro array.

nombreDia[dia]

Pasar parámetros a las funciones

Hasta ahora, hemos escrito funciones que elaboran datos que ya poseen y devuelven como mínimo un valor.

En realidad, es posible pasar uno o más datos (denominados parámetros) a la función en el momento en que esta se llama.

La función utilizará los datos pasados para sus elaboraciones y después estos influirán en el resultado de dicha función.

Comprobémoslo con un ejemplo:

<body><p id="output"></p><img id="carita" /><script type="text/javascript">function queDia(nombre) {const dia = new Date().getDay();const nombreDia = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];return `Hola ${nombre}! Feliz ${nombreDia[dia]}`;}document.getElementById('output').innerHTML = queDia('Alessandra');</script></body>

Puedes encontrar este ejemplo en el archivo FuncionesParametros .html

El comportamiento de esta función debería resultarte familiar; así podemos centrarnos en la gestión del parámetro.

Como puedes ver, la función, desde su definición, está predispuesta a aceptar un parámetro, nombre, en nuestro caso, que posteriormente será pasado (‘Alessandra’) en el momento en que la función es llamada.

En este ejemplo, hemos pasado un único parámetro, pero las funciones de JavaScript pueden aceptar más de uno.

Con este propósito, os proponemos otro ejemplo:

<script type="text/javascript">function cuantosDias(año, mes, dia, NombreEvento) {const hoy = new Date();const milsegEnUnDia = 1000 * 60 * 60 * 24; // los milisegundos de un día// indico a media noche la fecha de hoy, de no ser así la resta entre ambas fechas no nos dará la hora correctahoy.setHours(0, 0, 0, 0);const fechaEvento = new Date(año, mes - 1, dia)const diferenciaHoras = Math.abs(fechaEvento.getTimezoneOffset() / 60) - Math.abs(hoy.getTimezoneOffset() / 60);hoy.setHours(hoy.getHours() - diferenciaHoras);if (fechaEvento > hoy) {return `Faltan ${(fechaEvento.getTime() - hoy.getTime()) / milsegEnUnDia} días para ${NombreEvento}`;} else {return 'La fecha ya pasó'}}document.getElementById('output').innerHTML = cuantosDias(2017, 12, 25, 'Navidad');</script>

Puedes encontrar este ejemplo en el archivo FuncionesParametros1 .html

Esta vez la función es más compleja y prevé que se pasen cuatro parámetros: un año, un mes, un día y un evento. La función utilizará los primeros tres parámetros para crear una fecha y calcular cuántos días faltan para dicha fecha (obviamente, si esta todavía no ha pasado). El cuarto parámetro no es otro que un nombre para el evento representado por la fecha a partir de la cual calculamos los días que faltan.

Veamos cómo ocurre todo esto, puesto que la función contiene muchas novedades.

En primer lugar, además de la constante que representa la fecha, se crea otra que representa la duración de un día en milisegundos, porque la diferencia entre las fechas será devuelta exactamente en milisegundos y nosotros podremos utilizar el valor de esta constante para aplicar el resultado obtenido a varios días.

const milsegEnUnDia = 1000 * 60 * 60 * 24

Una vez hecho esto, indicamos la fecha de hoy a media noche. Si no lo hacemos, la fecha contiene también la hora del momento en que se ha creado y será más difícil de comparar con la fecha que crearemos con los parámetros pasados a la función que, en cambio, no contendrá un horario y, por tanto, hará referencia a la media noche:

hoy.setHours(0, 0, 0, 0);

setHours, efectivamente, ajusta la hora de una fecha. Requiere como argumentos hora, minutos, segundos y milisegundos.

En este momento, creamos la fecha con los parámetros que han sido pasados, sin olvidarnos de restar 1 al valor pasado para el mes, dado que JavaScript utiliza para los meses números que van del 0 (enero) al 11 (diciembre).

const fechaEvento = new Date(año, mes - 1, dia);

Para que nuestra función se comporte correctamente con o sin la horal legal, debemos ajustar el horario de la fecha de hoy de manera que tenga en cuenta el posible cambio de hora causado por la hora legal:

const diferenciaHoras = Math.abs(fechaEvento.getTimezoneOffset() / 60) - Math.abs(hoy.getTimezoneOffset() / 60);hoy.setHours(hoy.getHours() - diferenciaHoras);

Como ya sabéis (puesto que lo hemos visto en el capítulo ¡Hola mundo!), getTimezoneOffset devuelve la diferencia en minutos entre el UTC y la hora local. Si dividimos este resultado entre 60, obtendremos las horas.

En este momento, recurrimos al objeto Math, que todavía no había salido, y que nos permite ejecutar operaciones matemáticas. En concreto con abs() obtenemos la parte absoluta (positiva) de un número (en España, getTimezoneOffset devuelve siempre un número negativo).

Si restamos el resultado de la diferencia en horas entre los dos eventos, obtenemos el espacio que necesitamos para alinear la fecha actual con la fecha de nuestro evento: lo hacemos con setHours().


NOTAExisten diversas funciones que nos permiten elaborar un número con el objeto Math:•abs(): devuelve el valor absoluto de un número.•acos(): devuelve el arcocoseno en radianes.•asin(): devuelve el arcoseno en radianes.•atan(): devuelve el arcotangente como valor numérico comprendido entre ¬Π/2 y Π/2 radianes.•atan2(): devuelve el arcotangente del cociente de sus argumentos.•ceil(): devuelve el valor de su argumento redondeando por exceso al entero más cercano.•cos(): devuelve el coseno expresado en radianes.•exp(): devuelve el valor de e elevado al valor pasado como argumento.•floor(): devuelve el valor de su argumento redondeado por defecto al entero más cercano.•log(): devuelve el logaritmo natural en base e del número pasado como argumento.•max(): devuelve el valor máximo entre los argumentos que le han pasado.•min(): devuelve el valor mínimo entre los argumentos que le han pasado.•pow(): devuelve el valor del primer argumento pasado, elevado al valor del segundo argumento.•random(): devuelve un número aleatorio comprendido entre 0 y 1.•round(): devuelve su argumento redondeado al entero más cercano.•sin(): devuelve el seno expresado en radianes.•sqrt(): devuelve la raíz cuadrada.•tan(): devuelve la tangente.

Cuando las fechas se indican en la misma referencia horaria, con una instrucción if configuramos los mensajes que la función debe devolver: si el evento es posterior a hoy, es decir, su fecha es mayor que la fecha actual, el mensaje contendrá el número de días que faltan para el event; si no, indicará que la fecha ya ha pasado.

if (fechaEvento > hoy) {return `Faltan ${(fechaEvento.getTime() - hoy.getTime()) / milsegEnUnDia} días a ${NombreEvento}`;} else {return 'La fecha ya pasó'}

En nuestro ejemplo, hemos pasado a la función los valores (año-mes-día) para construir una fecha, pero nada nos impide pasar a la función directamente un objeto fecha:

<script type="text/javascript">function cuantosDias(fecha, evento) {let hoy = new Date();const milsegEnUnDia = 1000 * 60 * 60 * 24hoy.setHours(0, 0, 0, 0);const diferenciaHoras = Math.abs(fecha.getTimezoneOffset() / 60) - Math.abs(hoy.getTimezoneOffset() / 60);hoy.setHours(hoy.getHours() - diferenciaHoras);if (fechaEvento > hoy)return `Faltan ${(fecha.getTime() - hoy.getTime()) / milsegEnUnDia} días para ${evento}`;elsereturn 'La fecha ya pasó'}const fechaEvento =new Date(2017, 11, 25);document.getElementById('output').innerHTML = cuantosDias(fechaEvento, 'Navidad');</script>

Puedes encontrar este ejemplo en el archivo FuncionesParametros2 .html

Funciones anónimas

En los ejemplos con los que hemos trabajado hasta ahora, siempre hemos asignado un nombre a las funciones. JavaScript también permite crear funciones anónimas y asignarlas a una variable. Esta operación es posible porque en JavaScript function es un tipo que se puede almacenar en una variable. En otros lenguajes esto no es posible.

<script type="text/javascript">let suma = function (x,y){return x + y;}console.log(suma(34,67));</script>

Puedes encontrar este ejemplo en el archivo FuncionesAnonimas .html

Al utilizar la variable, podemos especificar entre sus paréntesis los parámetros que deseamos utilizar.

Las funciones anónimas también pueden ser utilizadas como parámetros para otras funciones. A lo largo de este libro, conoceremos ejemplos de este uso.

El área de validez de variables y constantes

Cuando se empiezan a utilizar funciones, es preciso prestar atención al área de validez de variables y constantes, es decir, a las partes del código donde variables y constantes pueden ser utilizadas. En nuestro ejemplo, hemos declarado la constante dia dentro de la función EsFinDeSemana.

function EsFinDeSemana() { const dia = new Date().getDay(); return dia === 0 || dia === 6;}

La constante existe solo dentro de la función y no puede ser utilizada fuera de ella. Por esta razón, podemos decir que el área de validez (en inglés scope) de la constante dia es la función esFinDeSemana. También se dice que dia es una constante local de la función esFinDeSemana. El mismo discurso vale para las variables.

Si definimos una variable o una constante fuera de una función, esta se denomina global y puede ser utilizada en cualquier lugar, incluso en posibles funciones, y mantiene su valor durante toda la ejecución del código.

Lo que acabamos de explicar es la teoría general referente al área de validez de las variables.

ECMAScript 6 presenta una aclaración más: el área de validez a nivel de bloque (blocked-level).

Tanto let como const generan variables y constantes a nivel de bloque.

Esto significa que, si en una función, por ejemplo, hay un bloque if y una variable o una constante se definen con let o const en el bloque if, estas existirán solo en el bloque y no en toda la función.

Por ejemplo:

function miFuncion() {if (true) {let variable = 123;}console.log(variable);}

La función anterior nos devolvería un error porque variable existe solo en el bloque if y no la podemos utilizar fuera de ella para mostrar el valor en la consola.

Debemos profundizar en esta cuestión, precisando que let fue introducida a partir de ECMAScript 6 (2015) y no está disponible en las versiones anteriores del programa.

En las versiones de JavaScript anteriores, para declarar una variable se utilizaba la palabra var, que también se utiliza en ECMAScript 6.

Tratemos de entender por qué es conveniente utilizar let.

Las instrucciones:

var nombreUsuario1 = 'Mario Rossi';let nombreUsuario2 = 'Paolo Bianchi';

desarrollan exactamente las mismas operaciones:

•Crean un área de memoria suficientemente amplia para conservar los caracteres de las cadenas.

•Asignan a esta área el nombre “nombreUsuario1”/“nombreUsuario2”.

La diferencia entre ambas consiste en su área de validez o scope.

Ya hemos dicho que el área de validez de let es el bloque. Pues bien, el área de validez de var, en cambio, es la función.

Veamos un ejemplo para explicarlo mejor; utilizamos una función que acepta como parámetros de entrada un array de números y calcula su suma y su media aritmética.

function mediaConVar1(numeros) {var suma = 0;for (var indice = 0; indice < numeros.length; indice += 1) {suma += numeros[indice];}var media = suma / numeros.length;return `Los ${numeros.length} números tienen suma=${suma} y media=${media}. El índice es ${indice}`;}

Ejemplo de uso de la función: mediaConVar1([84, 36, 61, 67, 22, 20, 22, 16, 79, 54]);

Puedes encontrar este ejemplo en el archivo Scope .html

En esta función hemos definido tres variables: suma, indice y media. Observa que están definidas en el punto en el que se utilizan: suma inmediatamente antes del bucle for del cálculo de la suma, indice dentro del bucle for y media después de que se ha calculado la suma.

La definición de variables en el punto en que se utilizan la primera vez es común a muchos otros lenguajes de programación.

Sin embargo, JavaScript, a diferencia de otros lenguajes, tiene un comportamiento peculiar (el término técnico es hoisting): las instrucciones var dentro de una función se ejecutan antes que todas las otras, sea donde sea que se encuentren en la función.

Para demostrar este efecto, añadimos a nuestra función una línea que escribe en la consola del navegador el valor de la variable media antes que la línea que la define:

var suma = 0;console.log(`media = ${media}`)for (var indice = 0; indice < numeros.length; indice += 1) {suma += numeros[indice];}var media = suma / numeros.length;

Pensaríamos que se produciría un error durante la ejecución, dado que utilizamos la variable media antes que su definición.

En lugar de eso, en la consola podemos ver:

media = undefined

(o media = "", según el navegador que se utilice)

Este mensaje significa que la variable media existe, pero que por el momento no tiene ningún valor. Esto se produce porque, de hecho, JavaScript, en fase de ejecución, reorganiza el código de esta manera:

function mediaConVar1bis(numeros) {var suma;var indice;var media;suma = 0;for (indice = 0; indice < numeros.length; indice += 1) {suma += numeros[indice];}media = suma / numeros.length;return `Los ${numeros.length} números tienen suma=${somma} y media=${media}. El índice es ${indice}`;}

donde todas las variables se definen al inicio de la función, pero no se les asigna un valor de inmediato.

Este comportamiento puede llevar a engaño incluso a los más expertos, puesto que se sugiere siempre definir explícitamente las variables al inicio de la función para que se vea que, efectivamente, es JavaScript quien gestiona el código:

function mediaConVar2(numeros) {var suma = 0, indice, media;for (indice = 0; indice < numeros.length; indice += 1) {suma += numeros[indice];}media = suma / numeros.length;return `Los ${numeros.length} números tienen suma=${suma} y media=${media}. El índice es ${indice}`;}

En el ejemplo, para crear un código más simplificado, hemos agrupado las definiciones en una única instrucción var (las variables separadas por comas) y hemos inicializado (mediante asignación), donde es necesario, el valor (suma = 0).

De este modo, con todas las variables al inicio, no es posible engañarse y utilizar una variable antes de que sea definida.

La solución de definir todas las variables al inicio, sin embargo, no es demasiado elegante y son pocos los lenguajes de programación que aconsejan o imponen esta práctica.

De hecho, esta puede causar errores en el código, dado que aleja el punto en que se define la variable del punto en que se utiliza y es más difícil mantener bajo control su gestión de forma correcta, sobre todo cuando el código es largo y complejo.

Así, en ECMAScript 6 (2015), para evidenciar este problema, se introdujo la instrucción let, que obliga a JavaScript a comportarse de una forma más parecida a los otros lenguajes: así se evita el hoisting, las variables se definen en el momento de la instrucción en que están creadas, no existen antes (por lo que no pueden ser utilizadas antes) y, si la definición se produce dentro de un bloque (entre dos {}), la variable no existe fuera de él.


NOTARecuerda que hemos dicho que el área de validez de let es el bloque, mientras que la de var es la función.

Si utilizamos let, la función propuesta se convierte en:

function mediaConLet(numeros) {let suma = 0;for (let indice = 0; indice < numeros.length; indice += 1) {suma += numeros[indice];}let media = suma / numeros.length;return `Los ${numeros.length} números tiene suma=${suma} y media=${media}. El índice es ${indice}`;}

Puedes encontrar este ejemplo en el archivo Scope2 .html

Si intentamos ejecutar esta función se producirá un error (visible en la consola del navegador) que indica que, en la instrucción de return, se utiliza una variable, indice, no definida.

De hecho, la variable indice, definida con let, existe solo dentro del bucle for (su área de validez es el bucle for).

Por lo tanto, debemos eliminar la lectura de la variable indice o definirla justo antes del bucle for (sin embargo, por norma general, las variables utilizadas como índice de un bucle no tienen ninguna utilidad fuera del bucle mismo):

return `Los ${numeros.length} números tienen suma=${suma} y media=${media}`;

Incluso si añadimos la línea:

console.log(`media = ${media}`)

antes del ciclo for se producirá un error, esta vez determinado por el intento de acceder a la variable media antes de su definición.


Formularios y eventos

Ha llegado el momento de aprender a leer el input del usuario con formularios adecuados. También veremos cómo ejecutar el código cuando se verifica un determinado evento.

Temas tratados

•Lectura y escritura en un formulario

•Eventos HTML y HTML5

•Respuesta a un evento

•Listener

•Subdivisión de cadenas en varias partes

En los ejemplos con los que hemos trabajado en el capítulo anterior hemos escrito directamente en el código los parámetros que se deben pasar a nuestras funciones, como la fecha respecto a la cual queremos calcular los días que faltan.

En esta ocasión queremos aprender a leer el input del usuario y a utilizarlo para nuestros procesos mediante JavaScript.

Continuaremos con el ejemplo que calcula el número de días que faltan para una fecha determinada, pero pediremos al usuario que nos proporcione dicha fecha.

Sin embargo, antes es necesario ver cómo leer el input del usuario. Volveremos al cálculo de los días al final del capítulo.

Naturalmente, para permitir al usuario que proporcione un input debemos preparar un formulario:

<body><form id='miFormulario'><input type="date" id='fecha'> <button type="button" onclick='leeFormulario()' id="boton">Envía</button></form><p id="output"></p><script>function leeFormulario() {document.getElementById("output").innerHTML = `La fecha seleccionada es: ${document.getElementById('fecha').value}`;}</script></body>

Puedes encontrar este ejemplo en el archivo Formulario .html

Hemos creado un formulario muy sencillo que contiene un campo <input> HTML5 de tipo fecha y un botón.

Debemos precisar varios aspectos sobre estos objetos.

<input type="date" id='fecha'><button type="button" onclick='leeFormulario()' id="boton">Envía</button>

En primer lugar, debemos decir que, en el momento en que se ha escrito este libro (a finales de 2017), la última versión disponible de Firefox no muestra para el campo de tipo fecha ningún elemento para la selección de la fecha, que por tanto deberá introducirse manualmente.

Por eso, te aconsejo que pruebes este ejemplo con un navegador distinto, como Chrome o Edge.

Además, observa que, en cuanto se refiere al botón, hemos tenido que especificar de forma explícita su tipo (type="button") para sobreescribir el comportamiento predeterminado de los botones en los formularios, que es el de submit, es decir, de envío del formulario.

Solo así, el botón puede comportarse como necesitamos y ejecutar la función Java-Script que está asociada a su evento onclick.

Podemos definir un evento como algo que ocurre en relación a un elemento de la página HTML, a menudo, aunque no siempre, vinculado a una acción del usuario. Cuando se utiliza en una página HTML, JavaScript es capaz de reaccionar a estos eventos.

En nuestro caso concreto, JavaScript es capaz de reaccionar al evento onclick sobre el botón con id=”boton”.

Como se puede ver, el evento onclick se verifica cuando un usuario hace clic sobre el botón.

La Tabla 7.1 resume los principales eventos HTML a los cuales JavaScript puede reaccionar.


NOTAVolveremos a los eventos ondragstart, ondragstart y ondrop en el capítulo dedicado al arrastre. En él, presentaremos también otros eventos que se utilizan para arrastrar objetos.

Tabla 7.1 – Eventos.


EventoDescripción
onchange Se verifica cuando un elemento HTML se modifica
onclick Se verifica cuando el usuario hace clic sobre un elemento HTML
onmouseover Se verifica cuando el usuario pasa el ratón por encima de un elemento HTML
onmouseout Se verifica cuando el usuario mueve el ratón fuera de un elemento HTML
onkeydown Se verifica cuando el usuario pulsa una tecla del teclado
onload Se verifica cuando el navegador ha completado la carga de la página
ondragstartSe verifica cuando el usuario empieza a arrastrar un elemento HTML5
ondragoverSe verifica cuando el usuario arrastra un elemento HTML5 sobre otro
ondropSe verifica cuando el usuario libera un elemento HTML5 tras haberlo arrastrado

Después de esta panorámica sobre los eventos, volvemos a nuestro código y observamos que, en este caso, pedimos a JavaScript que ejecute una función cuando se verifica el evento.

La función que se ejecuta es leeFormulario y se limita a leer el valor del campo <input id=fecha> y a escribirlo en la página:

document.getElementById("output").innerHTML = `La fecha seleccionada es: ${document.getElementById('fecha').value}`;

Para leer el dato contenido en el formulario, accedemos a su valor tras haberlo identificado con getElementById.

El valor del campo es una cadena de texto (Figura 7.1) en el formato aaaa-mm-dd. Debemos tenerlo en cuenta en nuestras futuras creaciones.


Figura 7.1 – El valor del campo fecha.

Del mismo modo que leemos el contenido del campo, también podemos escribirlo. Por ejemplo, queremos que, cuando se cargue la página, antes de la selección por parte del usuario, el campo muestre, como valor predeterminado, la fecha actual del sistema.

Corrige el código JavaScript del siguiente modo:

<script>const hoy = new Date();function leeFormulario() {document.getElementById("output").innerHTML = `La fecha seleccionada es: ${document.getElementById('fecha').value}`;}const año = hoy.getFullYear();const mes = hoy.getMonth() + 1;const dia = hoy.getDate();const fechaActual = `${año}-${mes}-${dia}`;document.getElementById("fecha").value = fechaActual;</script>

Puedes encontrar este ejemplo en el archivo Formulario1 .html

Fuera de la función que reacciona al evento clic sobre el botón, creamos un objeto fecha que contiene la fecha actual. Leemos y almacenamos el año, el mes y el día en constantes especiales y después utilizamos estas constantes para construir una cadena que representa la fecha en el formato que el campo de entrada se espera (aaaa-mm-dd).

const fechaActual = `${año}-${mes}-${dia}`;

Una vez hecho esto, asignamos al valor del campo fecha la cadena que acabamos de construir:

document.getElementById("fecha").value = fechaActual;

Ahora que ya sabemos leer y escribir en el campo de un formulario, podemos enriquecer nuestro ejemplo con el código JavaScript que calcula la distancia en días entre la fecha seleccionada y la fecha actual.

<form><input type="date" id='fecha'><button type="button" onclick='cuantosDias()' id="boton">Calcula cuántos días faltan para la fecha seleccionada</button></form><p id="output"></p><script>let hoy = new Date();function cuantosDias() {let fechaEvento = new Date(document.getElementById('fecha').value);console.log(fechaEvento);fechaEvento.setHours(0, 0, 0, 0);document.getElementById("output").innerHTML = fechaEvento;const milSegEnUnDia = 1000 * 60 * 60 * 24; // los milisegundos en un díahoy.setHours(0, 0, 0, 0);const diferenciaHoras = Math.abs(fechaEvento.getTimezoneOffset() / 60) - Math.abs(hoy.getTimezoneOffset() / 60);hoy.setHours(hoy.getHours() - diferenciaHoras);if (fechaEvento > hoy) {document.getElementById("output").innerHTML = `Faltan ${(fechaEvento.getTime() - hoy.getTime()) / milSegEnUnDia} días`;} else {document.getElementById("output").innerHTML = 'La fecha ya ha pasado'}}let año = hoy.getFullYear();let mes= hoy.getMonth() + 1;let dia = hoy.getDate();let fechaActual = `${año}-${mes}-${dia}`;document.getElementById('fecha').value = fechaActual;</script>

Puedes encontrar este ejemplo en el archivo Formulario2 .html

Gran parte de este código te debería ser familiar, porque no es otra cosa que una adaptación de lo que hemos visto en el capítulo anterior.

Existen solo algunas apreciaciones que hacer.

A diferencia de lo que hemos hecho con anterioridad, esta vez creamos la fecha no pasando números que representan año, mes y día, sino una cadena extraída de nuestro campo <input type="date">.

let fechaEvento = new Date(document.getElementById('fecha').value);


Figura 7.2 – La fecha ha sido creada a la una de la madrugada.

La fecha creada con una cadena de texto en el formato “aaaa-mm-dd”, que es el que nos devuelve el campo del formulario, es tratada como UTC y no como local.

En la práctica, para nosotros (que estamos +1 respecto al UTC), la fecha tiene como hora la 1 de la madrugada y no media noche, como cuando creamos la fecha partiendo de los números que representan año, mes y día.

Puedes comprobarlo fácilmente leyendo el resultado que se muestra en la consola (Figura 7.2).

Para solucionar este problema, bastará con indicar la fecha a medianoche como ya hemos hecho en alguna ocasión.

Operar con cadenas de texto

Paar evitar tener que indicar la fecha a media noche y/o provocar posibles problemas, otro enfoque podría ser el de extraer de la cadena de texto que leemos en el campo de entrada las partes que representan el año, el mes y el día y después utilizarlas para crear la fecha, como hemos hecho en el capítulo anterior.

Puedes sustituir las líneas que hemos analizado y resaltado en negrita en el código anterior con las líneas siguientes:

const partesFecha = document.getElementById('fecha').value.split('-');const fechaEvento = new Date(partesFecha[0],partesFecha[1]-1,partesFecha[2] );console.log(fechaEvento);

Puedes encontrar este ejemplo en el archivo Formulario3_cadenas .html

La fecha se creará con el horario de medianoche (Figura 7.3).


Figura 7.3 – La fecha creada a medianoche.

Pero vamos a intentar entender cómo funciona este código. Todo se basa en el método split que podemos aplicar a las cadenas de texto.

Split requiere como argumento un separador y devuelve un array que contiene las partes de la cadena de texto a las cuales se aplica el método divididas según el separador. El separador, obviamente, no forma parte de las cadenas resultantes.

En nuestro caso, suponiendo que hayamos seleccionado como fecha el 25/12/2018, la cadena de texto inicial será:

"2018-12-25"

Por lo que nuestra separador será “-” y el array resultante contendrá los valores siguientes:

partesFecha[0] = 2018partesFecha[1] = 12partesFecha[2] = 25

Naturalmente, el valor para el mes disminuye en una unidad, dado que new Date espera el mes expresado con un número del 0 al 11.

Gestores de eventos

En todos los ejemplos anteriores, hemos gestionado los eventos con gestores en línea de tipo onEvent (onClick, onLoad…); sin embargo, JavaScript dispone de otro tipo de sintaxis que prevé el uso de un listener, es decir, de una función que “escucha” (listen) esperando el evento que recibe como primer argumento y, si este se verifica, ejecuta el código que recibe en los argumentos siguientes.

Para probar esta sintaxis, vamos a escribir el primer ejemplo propuesto en este capítulo:

<form id=’miFormulario’><input type=”date” id=’fecha’><button type=”button” onclick=’leeFormulario()’ id=”boton”>Envía</button></form><p id=”output”></p><script>function leeFormulario() {document.getElementById(“output”).innerHTML = `La fecha seleccionada es: ${document.getElementById(‘fecha’).value}`;}document.getElementById("boton").addEventListener('click', leeFormulario)</script>

Puedes encontrar este ejemplo en el archivo Formulario_listener .html

Observa que hemos llamado el método addEventListener() sobre el botón (identificado, como es habitual, mediante getElementById) y, como primer argumento, le hemos pasado el evento que queremos interceptar, mientras que como segundo argumento le hemos pasado la función que se debe ejecutar si el evento se verifica.

Los nombres de los eventos que podemos pasar a addEventListener() son iguales a los que hemos visto anteriormente, pero sin el prefijo on.


NOTAEl método addEventListener acepta un tercer argumento booleano que permite definir si el evento debe ser definido en fase de captura (true) o en fase de bubbling (false). Si elegimos gestionar el evento en fase de captura (o capturing), el evento primero es capturado por el elemento más externo y, después, difundido a los elementos internos. Pasa lo contrario con la gestión en fase de bubbling, donde el evento primero es capturado y gestionado por el elemento más interno y después se propaga a los elementos más externos. Este es el comportamiento predefinido, si no se asigna un valor al tercer argumento de addEventListener.

Además de pasar una función, también es posible escribir directamente el código que se tiene que ejecutar tras la verificación del evento mediante una función anónima, como hemos hecho en el código siguiente:

<style>.colorPicker { width: 50px; height: 50px; float: left; margin: 5px; border-style: solid;}</style><div class="colorPicker" id="negro" style="background-color:black"></div><div class="colorPicker" id="blanco" style="background-color:white"></div><div style="clear:both;"></div><div id="texto" style="width:400px; height: 400px; border-style:solid">…</div><script>document.getElementById("negro").addEventListener('click', function () { document.getElementById("texto").style.backgroundColor = 'black'; document.getElementById("texto").style.color = 'white';});document.getElementById("blanco").addEventListener('click', function () { document.getElementById("texto").style.backgroundColor = 'white'; document.getElementById("texto").style.color = 'black';})</script>

Puedes encontrar este ejemplo en el archivo Formulario_listener1 .html

Si ejecutas este código en el navegador, podrás ver dos cuadros, uno blanco y otro negro (id=”negro” e id=”blanco”) y un espacio con texto (Figura 7.4).


Figura 7.4 – La página en el navegador.

Si haces clic sobre uno de los cuadros verás como cambia el color de fondo y el de los caracteres del área con el texto.

A los dos cuadros se ha añadido un listener (analizamos solo uno, puesto que el otro funciona de modo idéntico) que responde al evento click:

document.getElementById("blanco").addEventListener('click', function () { document.getElementById("texto").style.backgroundColor = 'white'; document.getElementById("texto").style.color = 'black';})

Al pulsar sobre el cuadro blanco, se ejecuta una función anónima que configura el fondo blanco para el área de texto y el color negro para sus caracteres.

Para realizar estas modificaciones, hemos utilizado las propiedades del objeto de Java-Script style, que representa una instrucción de estilo para un objeto. Sus propiedades corresponden a las propiedades de estilo CSS.

También se necesita una función anónima cuando en el gestor del evento se desea llamar una función a la cual se pasan parámetros.

Modificamos el ejemplo anterior para tener una función que modifica el color de fondo y de los caracteres del área de texto. A esta función debemos pasarle los colores que deseamos utilizar.

Mostramos solo la parte <script> del archivo, puesto que el resto no cambia respecto al ejemplo anterior:

<script>function configuraFondo(colorFondo, colorTexto) { document.getElementById("texto").style.backgroundColor = colorFondo; document.getElementById("texto").style.color = colorTexto;}document.getElementById("negro").addEventListener('click', function () { configuraFondo('black', 'white');});document.getElementById("blanco").addEventListener('click', function () { configuraFondo('white','black');})</script>

Puedes encontrar este ejemplo en archivo Formulario_listener2 .html

Para completar este ejemplo, añadimos el código que muestra un puntero con forma de mano cuando el ratón pasa por encima de los cuadros y le devuelve la forma clásica de flecha cuando el ratón se aleja de ellos: para ello, debemos utilizar los eventos mouseover y mouseout.

Antes de escribir los gestores para estos eventos, escribimos la función que queremos llamar cuando los eventos se verifican.

function configuraRaton(puntero) { document.body.style.cursor = puntero;}

Utilizamos la propiedad cursor de style. El aspecto del puntero se pasará como parámetro cuando se llame la función en los gestores de los eventos:

document.getElementById("negro").addEventListener('mouseover', function () { configuraRaton('pointer');});document.getElementById("blanco").addEventListener('mouseover', function () { configuraRaton('pointer');})document.getElementById("negro").addEventListener('mouseout', function () { configuraRaton('auto');});document.getElementById("blanco").addEventListener('mouseout', function () { configuraRaton('auto');}

Los valores pasados a la función configuraRaton son los valores que pueden ser aceptados por la propiedad cursor. Nosotros hemos utilizado los más comunes: pointer, que corresponde a la manita que señala los elementos activos y los vínculos, y auto, que corresponde al puntero normal en forma de flecha blanca. Para todos los otros valores disponibles, puedes dirigirte a la página https://www.w3schools.com/jsref/prop_style_cursor.asp.


NOTARetomaremos este ejemplo y profundizaremos en él en el capítulo dedicado a this.

En este capítulo, solo hemos hecho mención del uso de los listeners. Volveremos a hablar de ellos más adelante, en el capítulo dedicado a las funciones avanzadas y en el que también trataremos el elemento this.


Expresiones regulares

Las expresiones regulares describen un patrón de caracteres y se pueden utilizar para verificar que el texto se ajusta a un modelo específico.

Temas tratados

•Creación de patrones

•Uso de expresiones regulares

•Probar si un elemento es '', null, undefined, false, 0 o NaN

•Unir los valores de un array en una única cadena de texto

•forEach para ejecutar un bucle sobre todos los elementos de un array

Las expresiones regulares describen un patrón de caracteres y pueden ser utilizadas para verificar que un texto se ajusta a un modelo específico.

Es decir, estas expresiones nos permiten verificar que un valor representa, como mínimo en su forma (verificar la sustancia es un poco más complicado), el dato que efectivamente se solicita.

Imagina un módulo que requiere proporcionar una dirección de correo electrónico. Antes de memorizar el dato, necesitamos estar seguros de que se trata efectivamente de una dirección de correo electrónico. Esto puede valer también para otros tipos de datos, como códigos fiscales o partidas de IVA.

Las expresiones también tienen otro uso, a saber, la posibilidad de manipular las cadenas basadas en estructuras predefinidas.

Para utilizar las expresiones regulares, es preciso definir un patrón o pattern, un modelo con el cual comparar la cadena de texto a verificar.

La convalidación de un dato insertado en un formulario, con la introducción en HTML5 del atributo pattern, ha sido simplificada y ya no necesita código JavaScript.

En cualquier caso, HTML5, para la definición de los patrones de control, utiliza la sintaxis de las expresiones regulares de ECMAScript.

Por esta razón, todo cuanto expongamos en este capítulo es válido también para la validación de formularios HTML5.

Definir los patrones para las expresiones regulares

Antes de empezar con los ejemplos prácticos, queremos exponer los principios básicos con los cuales se construyen los patrones de las expresiones regulares, que después podremos dar por sabidos.

El concepto básico es que es preciso encontrar el modo de describir qué caracteres son aceptables en la expresión regular escrita (cifras, letras, caracteres especiales, etc.). Para ello, se pueden utilizar los símbolos mostrados en las tablas siguientes.

Tabla 8.1 – Clases de caracteres.


CarácterRepresenta
\dCualquier cifra del 0 al 9
\DCualquier carácter (letras, símbolos, pero no cifras)
\wCualquier carácter del alfabeto latino, mayúsculas o minúsculas, cifras y el guion bajo(A-Z, a-z, 0-9, _)
\WCaracteres especiales, no caracteres alfabéticos en minúscula o mayúscula, cifras, ni guiones bajos o espacios
\sUn carácter que indica un espacio (espacio, tabulación, retorno de carro, etc., traducible en blanco, CR, LF, FF, HT, VT)
\SCualquier carácter, excepto aquellos que indican un espacio
.Cualquier carácter único
\tUn carácter de tabulación
\rUn retorno de carro (carriage return)
\nNueva línea
\vTabulación vertical
\fForm feed para enviar la página a la impresora y avanzar al módulo siguiente
[\b]Retroceso
\0Carácter nulo
\cXDonde X es una letra de la A a la Z. Encuentra un carácter de control en una cadena de texto
\Tiene dos usos:• indica que el carácter siguiente no debe ser tratado literalmente, sino que es un carácter especial en la expresión regular. \d no indica la letra “d” sino una cifra, como hemos visto anteriormente;• indica que un carácter que normalmente se utiliza como carácter especial es tratado literalmente. \. no indica un carácter único cualquiera como hemos visto anteriormente, sino el carácter “.”

Tabla 8.2 – Conjunto de caracteres.


CarácterRepresenta
[...]Cualquiera de los caracteres indicados entre los corchetes
[^...]Cualquier carácter, excepto los que se indican entre corchetes

Tabla 8.3 – Alternativas.


CarácterRepresenta
x|yEncuentra o x o y. De forma más general, | indica una alternativa entre lo que se encuentra a su derecha y a su izquierda

Tabla 8.4 – Límites.


CarácterRepresenta
^Identifica el inicio de una cadena de texto. Por ejemplo,/^A/ identifica la primera “A” de “Alessanda”, pero no las siguientes
$Identifica el final de una cadena de texto. Por ejemplo, /$o/ identifica la “o” de “perro” pero no de “mona”
\bIdentifica los límites de una palabra, es decir, la posición en que un carácter (no especial) no es seguido o precedido por un carácter (no especial).Por ejemplo, /\bn/ identifica la “n” de “noche” o de “con”, pero no de “ángulo”
\BIdentifica los límites sin palabra, a saber, los casos en que un carácter y el siguiente o el precedente son del mismo tipo (caracteres normales o caracteres especiales)

Tabla 8.5 – Repeticiones.


CarácterRepresenta
{n}El elemento precedente se repite n veces
{n,}El elemento precedente se repite n veces o más. En la práctica, n es el número mínimo de repeticiones
{n,m}El elemento precedente está repetido de un mínimo de n veces a un máximo de m veces
*El elemento precedente se repite 0 o más veces
?El elemento precedente se repite 0 o una vez
+El elemento precedente se repite una o más veces

Tabla 8.6 – Declaraciones.


CarácterRepresenta
x(?=y)Identifica un carácter x solo si es seguido por un carácter y

Las expresiones regulares permiten agrupar partes de caracteres para un posible uso posterior. El grupo se define como “capturing” si es recordado y si no, como “non capturing”.

Tabla 8.7 – Agrupación y almacenamiento


CarácterRepresenta
(x)Identifica el grupo x y recuerda el grupo identificado
\nDonde n es un número entero positivo
(?:x)Identifica z, pero no lo recuerda

Las banderas o flags se sitúan al final del patrón y modifican su comportamiento.

Tabla 8.8 – Flags.


CarácterRepresenta
gIdentifica todas las coincidencias del patrón y no se detiene en la primera
iNo distingue entre mayúsculas y minúsculas
mLínea múltiple; trata los caracteres de inicio y fin (^ e $) como si trabajaran en varias líneas (es decir, identifica el inicio y el final de cada línea individual)
uEl patrón es tratado como unicode. Presentado con ECMAScript 6
yEjecuta una búsqueda “sticky”, es decir, identifica el patrón solo a partir de la posición indicada en la propiedad lastIndex de la expresión regular. Presentado en ECMAScript 6

En JavaScript, los patrones pueden ser escritos según tres sistemas de notación.

Suponiendo que tenemos el patrón [aeiou]\d y el flag g, podemos escribir de una de las siguientes maneras:

•/patron/flags: let patron = /[aeiou]\d/g;

•new RegExp(patron[, flags]): let patron = new RegExp('[aeiou]\\d','g');

•RegExp(patron[, flags]): let patron = RegExp('[aeiou]\\d', 'g').

Observa que en la segunda y tercera solución, el patrón se escribe como una cadena de texto y, por tanto, para conseguir que el carácter \ asuma su significado de metacarácter y transforme el significado de d (que no tiene que representar la letra d, sino cualquier número), debemos situar otra barra inclinada antes de la que transforma el d: \\d.

Esta práctica se denomina escape del carácter.

Una vez dicho esto, la primera solución nos parece la más inmediata y rápida, por lo que será la que adoptaremos en los ejemplos propuestos en este capítulo. Sin embargo, naturalmente, cada uno es libre de proceder como prefiera.

Aplicar expresiones regulares

Después de esta introducción/referencia, podemos pasar a aplicar las expresiones regulares en algunos ejemplos.

Podemos empezar aplicando a una expresión regular el método test() para verificar si una cadena de texto se corresponde con un determinado patrón.

let texto = "ape5"let patron = /[aeiou]\d/g;let correspondeAPatron = patron.test(texto);console.log(correspondeAPatron);

Puedes encontrar este ejemplo en el archivo test .html

En este caso, en la consola leeremos true, porque nuestro texto se corresponde con patron, en cuanto contiene una vocal (uno de los caracteres entre corchetes) inmediatamente seguida de una cifra. Es decir, que la parte de la cadena que se corresponde con el patrón es “e5”.

Dejamos invariable el código y la cadena texto; vamos a modificar el patrón y ver los distintos resultados del método test.

Tabla 8.9 – Ejemplos de patrones.


PatrónResultado testNotas
/^[aeiou]\dfalseLa búsqueda se realiza al inicio de la cadena (^)
[aeiou]\d$trueLa búsqueda se realiza al final de la cadena (^)
/[aeiou]+\d/trueLa vocal se busca una o más veces
[aeiou]\\.\dfalseEntre la vocal y el número debe haber también un punto (\\.). Observa que delante del carácter punto (.) hemos tenido que añadir un carácter de barra invertida (\), es decir, el carácter de escape que suspende el significado especial del carácter que lo sigue dentro de la expresión regular. En este caso, sirve para especificar que el carácter punto debe tener su significado literal y no su valor especial en la expresión regular (el punto indica un carácter cualquiera), es decir, su valor de metacarácter

Seguimos con otro ejemplo similar, esta vez permitimos al usuario la inserción del texto que se desea verificar con una expresión regular: veremos si el texto insertado contiene alguna cifra.

<form><input type="text" id='texto'><button type="button" onclick='contieneNumeros()' id="boton">Comprueba si el texto insertado contiene números</button></form><p id="output"></p><script>function contieneNumeros() {let texto = document.getElementById('texto').value;let numeroPatron = /\d+/;let contieneNumeros = numeroPatron.test(texto);contieneNumeros ? document.getElementById('output').innerHTML = "El texto insertado contiene números" :document.getElementById('output').innerHTML = "El texto insertado NO contiene números"}</script>

Puedes encontrar este ejemplo en el archivo contieneNumeros .html

Observa el patrón que hemos utilizado:

let numeroPatron = /\d+/;

El patrón espera una cifra (\d) repetida más de una vez (+).

Extraer texto con una expresión regular

En los ejemplos anteriores, nos hemos limitado a verificar si un texto contenía una parte de cadena de texto que se corresponde con un patrón determinado.

Ahora queremos probar de extraer la parte de la cadena que se corresponde con una expresión regular.

Supongamos, por ejemplo, que deseamos extraer el código postal de una dirección:

let direccion = 'Plaza del Ayuntamiento, 08029 Barcelona'let cpPatron = /\d{5}/;let cp = direccion.match(cpPatron);console.log(cp);document.getElementById('output').innerHTML = `El CP e: ${cp}`;

Puedes encontrar este ejemplo en el archivo extraerCP .html

Para ello, utilizamos el método match() de la cadena de texto (no de la expresión regular como pasaba con el método test()) al cual pasamos como argumento el patrón de la expresión regular.

El patrón que utilizamos prevé una repetición de 5 cifras:

cpPatron = /\d{5}/;

El método match() nos devuelve un array (Figura 8.1) que contiene las coincidencias encontradas. En este caso, la coincidencia identificada solo es una y, por tanto, podemos tranquilamente utilizar la variable que contiene el array para mostrar un valor en el <div> output de nuestra página.


Figura 8.1 – La consola muestra que el método match() nos devuelve un array.

En nuestro ejemplo, hemos escrito la dirección de la cual se extraerá el CP directamente en el código. ¿Qué ocurriría si dejáramos que fuera el usuario quien insertara la dirección mediante un formulario y este insertara algo que no contuviera un CP?

<form><label for="texto">Escribe la dirección de la cual quieres extraer el CP:</label><input type="text" id='texto'><button type="button" onclick='extraeCP()' id="boton">Extrae CP</button></form><p id="output"></p><script>function extraeCP() {let direccion = document.getElementById('texto').value;let cpPatron = /\d{5}/;let cp = direccion.match(cpPatron);if (!cp) { document.getElementById('output').innerHTML = 'El texto insertado no contiene un CP';} else { document.getElementById('output').innerHTML = `El CP es: ${cp}`;}}</script>

Puedes encontrar este ejemplo en el archivo extraesCP1 .html

Si el usuario no inserta un CP (o algo que tenga forma de CP), el array CP tiene un valor null (Figura 8.2).


Figura 8.2 – Si la cadena escrita por el usuario no contiene un conjunto de 5 cifras, el CP es null.

Es preciso verificar si CP no tiene un valor y, en ese caso, actuar en consecuencia.

Para ello, utilizamos el operador not !, que niega aquello que viene a continuación.

Es como si pidiéramos a la instrucción if que verificara si CP no tiene un valor.

!cap resulta true si la variable cap es '' (cadena vacía), null, undefined, false, 0 o NaN (not a number); en nuestro caso, es null.

Una vez realizada esta comprobación, podemos mostrar los mensajes oportunos.

En nuestro ejemplo anterior, hemos supuesto que la dirección insertada por el usuario contiene un único valor que corresponde a nuestra expresión regular. ¿Y si fueran dos, como un número postal de 5 cifras y después un CP? ¿Y si, por ejemplo, la dirección fuera “Calle del Triunfo, 07891 08029 Barcelona”?

function extraeCP() { let direccion = document.getElementById('texto').value; let cpPatron = /\d{5}/g; let cp = direccion.match(cpPatron); console.log(cp); if (!cp) { document.getElementById('output').innerHTML = 'El texto insertado no contiene un CP'; } else { document.getElementById('output').innerHTML = `El CP es: ${cp[cp.length-1]}`; }}

Puedes encontrar este ejemplo en el archivo extraerCP2 .html

En primer lugar, debemos modificar nuestro patrón, puesto que, de no ser así, match() se detendrá durante la búsqueda en la primera coincidencia del patrón (Figura 8.3), es decir, en la parte que, en nuestro ejemplo, indica la dirección postal.


Figura 8.3 – La expresión regular identifica solo la primera coincidencia del patrón.

Es preciso añadir al patrón el flag g, de manera que la búsqueda no se interrumpa y se identifiquen todas las coincidencias con nuestro patrón (Figura 8.4).

let capPattern = /\d{5}/g;


Figura 8.4 – Con el flag g se identifican todas las coincidencias del patrón.

Ahora ya solo nos queda por descubrir, leyendo la propiedad length, cuántos elementos contiene el array cp y, después, leer el valor situado en última posición (length-1, dado que el índice del array empieza desde 0):

cp[cp.length-1]

Con el mismo principio, podemos realizar otro ejemplo. Supongamos que tenemos una caja de texto en la cual pedimos al usuario que escriba un código numérico (por ejemplo, una matrícula) que podría escribirse en distintos formatos: /(X 0000 XX, 0000 XXX, XX 0000 XX…

Nos interesa extraer la parte numérica y combinarla sin utilizar espacios ni separadores, eliminando cualquier otro carácter.

<form><label for='texto'>Escribe el número de tu matrícula:</label><input type="text" id='texto'><button type="button" onclick='envía()' id="boton">envía el dato insertado</button></form><p id="output"></p><script>function envia() { let codigoMatricula = document.getElementById('texto').value; let numerosPatron = /\d+/g; let numeros = codigoMatricula.match(numerosPatron); let matriculaCorrecta = numeros.join(''); document.getElementById('output').innerHTML = matriculaCorrecta;}</script>

Puedes encontrar este ejemplo en el archivo unificaNumeros .html

La única novedad de este código consiste en el método join() del array, que nos permite unificar los elementos de un array en una única cadena. Nosotros hemos elegido no añadir ningún separador entre los elementos en la cadena resultante, por lo que hemos pasado al método join una cadena vacía (''), pero es posible elegir cualquier separador, simplemente pasándolo como argumento de join.

Бесплатный фрагмент закончился.

1 442,98 ₽

Жанры и теги

Возрастное ограничение:
0+
Объем:
344 стр. 125 иллюстраций
ISBN:
9788426727701
Издатель:
Правообладатель:
Bookwire
Формат скачивания:

Похожие книги