Tema 3
Desarrollo Web: Full Stack
Tema 3. JavaScript avanzado
Índice
Esquema
Ideas clave
3.1. Introducción y objetivos
3.2. Definición e invocación de funciones
3.3. Argumentos
3.4. Funciones flecha
3.5. Funciones de retrollamada o callback
3.6. Funciones de orden superior
3.7. Objetos literales
3.8. El objeto this
3.9 Promesas y funciones asíncronas
3.10. Closures
3.11. Código de apoyo y ejercicios
3.12. Referencias bibliográficas
A fondo
Programación basada en eventos
Métodos sobre arrays
Test
Esquema
Desarrollo Web: Full Stack 3
Tema 3. Esquema
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.1. Introducción y objetivos
Dos términos que constituyen el núcleo de JavaScript son los objetos y las
funciones. Por un lado, los objetos engloban las distintas formas de agrupar
información (arrays, sets, mapas, etc.). Por otro lado, las funciones son las
instrucciones que van a operar con esos conjuntos de información y devolvernos
información nueva. Esto no es otra cosa, sino el objetivo básico de cualquier lenguaje
de programación y, por extensión, cualquier programa.
Dicho de otra manera, los objetos y las funciones son lo que hacen de JavaScript un
lenguaje de programación completo, además del más usados en la historia de la
informática y la tecnología.
Pero JavaScript nos tiene guardada una sorpresa más: las funciones son también
objetos. Esto quedará más resaltado sobre todo cuando estudiemos las funciones
de
retrollamada o callbacks.
Más concretamente, en este tema hablaremos de:
▸ Cómo una función puede recibir argumentos.
▸ La notación nueva para definir funciones de manera rápida en ES6.
▸ Las funciones asociadas a arrays, sets y mapas, también conocidas como funciones
de orden superior.
▸ La definición directa de objetos mediante su notación literal.
▸ El objeto this.
Desarrollo Web: Full Stack 4
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.2. Definición e invocación de funciones
Existen varias maneras de definir una función, pero la más recomendable es la
siguiente:
Figura 1. Declaración de una función 1. Fuente: elaboración propia.
Estrictamente hablando, lo que ha ocurrido es que hemos asignado una función
anónima (sin nombre) a una variable. No hay problema en darle un nombre a la
función, pero no tiene ninguna utilidad especial:
Figura 2. Declaración de función 2. Fuente: elaboración propia.
El comportamiento de una función puede ser modificado mediante los parámetros de
entrada que comentaremos más tarde. Fíjate también que ambos ejemplos acaban
en un punto y coma (;) en la última línea. Esto es así porque se trata de una
instrucción de asignación y, como tal, debe acabar en este símbolo (aunque el
cuerpo de la función tenga varias líneas).
Desarrollo Web: Full Stack 5
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Todas las funciones tienen una propiedad, su nombre (name). Es posible acceder
a ella con la propiedad .name de la siguiente manera:
Figura 3. Cómo acceder a una propiedad de una función. Fuente: elaboración propia.
Esto debería resultarte curioso con respecto a otros lenguajes de programación.
Acabamos de invocar un método/propiedad sobre una función. Esto solo puede
significar una cosa, las funciones son objetos. Otra cosa que te resultará curiosa es
que, si lo piensas, en los ejemplos anteriores hemos usado una notación literal para
definir una función. ¿Acaso no existe una notación para definir funciones que haga
uso de constructores? Pues sí, es esta:
Figura 4. Declaración de función 3 . Fuente: elaboración propia.
Sin embargo, no se recomienda su uso, ya que resulta un poco farragoso. Solo lo
hemos indicado a nivel académico.
Invocación de funciones
Una vez que hemos definido nuestra función, ya podemos invocarla. Al hacerlo, se
ejecutará el conjunto de instrucciones que estaba empaquetado en la misma. Para
ello, simplemente tenemos que sufijar un paréntesis de apertura y cierre al nombre
de la variable que habíamos asignado antes a la función. Ejemplo:
Desarrollo Web: Full Stack 6
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Figura 5. Invocación de funciones. Fuente: elaboración propia.
Si no pusiéramos los paréntesis, JavaScript nos recuerda el hecho de que la variable
funcionSaluda apunta, efectivamente, a una función:
Figura [Link] de los paréntesis para invocar funciones. Fuente: elaboración propia.
Si te has dado cuenta, en muchos ejemplos aparecía la expresión «devuelve tal o
cual». Esto es así porque la función de turno, efectivamente, devolvía un valor
derivado. Al igual que en matemáticas, las funciones devuelven «cosas» (no solo
números). Para indicar que una función retorna algún tipo de información, se usa la
cláusula return. Ejemplo:
Figura 7. Palabra reservada return. Fuente: elaboración propia.
Cuando asignamos la invocación de una función a una variable, esta inicializa (o
actualiza) con el valor devuelto por la función:
Figura 8. Guardar el resultado devuelto por una función. Fuente: elaboración propia.
Esquemáticamente, una función suele representarse como una caja negra en la que,
Desarrollo Web: Full Stack 7
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
por un lado, se ingresan parámetros y, en el otro, se obtiene un resultado tras operar
con esos parámetros.
Figura 9. Representación esquemática de una función. Fuente: elaboración propia.
Desarrollo Web: Full Stack 8
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
En el siguiente vídeo, Entendiendo las funciones en JavaScript, se resumen los
conceptos que hemos explicado en esta sección y se introducen nuevos ejemplos:
Entendiendo las funciones en JavaScript
Accede al vídeo:
[Link]
42e6-88df-b1d800df1e5c
Desarrollo Web: Full Stack 9
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.3. Argumentos
Los argumentos o parámetros son los valores que se les pasan a las funciones
como entrada.
Desde dentro de la función, las instrucciones que la componen tienen acceso a estos
parámetros. En el siguiente ejemplo calculamos la energía asociada a una masa
usando la famosa ecuación de Einstein:
La implementación quedaría así:
Figura 10. Fórmula de la energía en JavaScript. Fuente: elaboración propia.
El ejemplo anterior tiene dos cosas a resaltar.
En primer lugar, una función tiene acceso a valores y variables externos que se
encuentran dentro del mismo bloque.
Estos bloques pueden corresponderse a ámbitos locales o al ámbito global. En el
ejemplo anterior, la función tiene acceso a la constante c (la velocidad de la luz) sin
mayor problema, ya que esta ha sido definida en el mismo bloque que contiene la
definición de la función energia (en este caso es el bloque correspondiente al ámbito
global).
Desarrollo Web: Full Stack 10
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Por otro lado, en el ejemplo también se muestra la nueva manera introducida en ES6
para expresar la operación matemática elevado a: base**exponente. Antes de ES6
era necesario utilizar la función [Link](base, exponente). Luego, veremos que
Math es en realidad un objeto que define un espacio de nombres (que a su vez
define la función pow()).
A diferencia de otros lenguajes de programación, en JavaScript no es
necesario especificar cuántos parámetros son necesarios en una
función. Tampoco es necesario avisar del tipo de estos argumentos.
Pero ¿cómo podemos, desde dentro de una función, acceder a un número arbitrario
de argumentos? Para ello, JavaScript cuenta con una variable especial llamada
arguments. Esta variable no es más que una especie de pseudoarray (no es un array
real) que contiene cada uno de los parámetros que se pasan a la función en orden.
Podemos referirnos a cada uno de ellos usando la misma notación para seleccionar
elementos de los arrays. En el siguiente ejemplo simplemente devolvemos el primer
elemento que se nos pasa:
Figura 11. Definición e invocación de una función. Fuente: elaboración propia.
Desarrollo Web: Full Stack 11
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
A partir del ES6 existe una mejor forma de trabajar con un número arbitrario de
parámetros y esta es con el operador de propagación (...). Este operador
transforma todos los argumentos pasados en un array «de verdad»:
Figura 12. Operador de número variable de argumentos. Fuente: elaboración propia.
Internamente, el operador (...) transforma 4, 5, 1, 3 en [4, 5, 1, 3].
Desde el ES6, las funciones pueden tener parámetros por defecto. Es decir, si no
pasamos un parámetro concreto, se tomará uno concreto predefinido. Ejemplo:
Figura 13. Función con argumentos por defecto. Fuente: elaboración propia.
Desarrollo Web: Full Stack 12
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.4. Funciones flecha
Con ES6 también se introduce una nueva sintaxis para definir funciones, esta nueva
manera es más limpia y directa. Está inspirada en el superset de JavaScript llamado
CoffeeScript.
Las funciones flecha (o arrow functions) pueden identificarse, precisamente, por la
presencia de una flecha (=>). Este símbolo separa los parámetros que recibe una
función del cuerpo de la función.
Ejemplo:
Figura 14. Uso de función flecha. Fuente: elaboración propia.
El ámbito de uso de las funciones flecha es, sobre todo, para especificar funciones
que sean cortas: pocas líneas de código (normalmente tan solo una) y lógica sencilla.
Además, tienen estas características:
▸ Si solo reciben un parámetro, no es necesario usar paréntesis.
▸ No es necesario usar la notación de bloque ({}) si la función solo tiene una línea de
código.
▸ La cláusula return tampoco es necesaria si la función solo tiene una línea. En este
caso, se devuelve el valor que retorne la instrucción de esa precisa línea.
Veamos un ejemplo:
Figura 15. Declaración de función flecha. Fuente: elaboración propia.
Desarrollo Web: Full Stack 13
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
En la función sumarDosNumeros tenemos una función que recibe dos parámetros (a
y b), los suma y devuelve el resultado de la suma. Es como si hubiera un return a + b
en lugar de solo a + b.
En el siguiente ejemplo, la función flecha es un poco más compleja. Para empezar,
consta de dos líneas de código, por lo que ya hay que poner llaves indicadoras de
bloque ({}). Por las mismas razones, también es necesario indicar explícitamente el
valor devuelto con return.
Figura 16. Función flecha más extensa. Fuente: elaboración propia.
Desarrollo Web: Full Stack 14
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.5. Funciones de retrollamada o callback
Las funciones de retrollamada, o más comúnmente conocidas como callbacks, son
funciones que se pasan como parámetro a otras funciones. Sí, además de cadena de
texto, números, arrays, objetos, etc., también podemos pasar funciones. No podía
ser de otra manera, ya que las funciones también son objetos. Por ejemplo, una
función puede tener propiedades:
Figura 17. Función con propiedades. Fuente: elaboración propia.
Puedes comprobar por ti mismo cómo lo que hemos hecho es definir una función
(funConProps) desde la cual ella misma accede a una propiedad
([Link]). Esta propiedad es inicializada/modificada después.
Pero volvamos a las callbacks.
El objetivo de una callback es que sea invocada en algún momento a lo
largo de la función que la recibe.
Las callbacks son la base de la programación basada en eventos, la cual es muy
usada en aplicaciones basadas en JavaScript.
Puedes consultar más sobre la programación basada en eventos de JavaScript
en la sección de A fondo, Programación basada en eventos.
Veamos un ejemplo sencillo de definición y uso de una callback:
Desarrollo Web: Full Stack 15
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Fragmento de JavaScript 18. Función con una callback. Fuente: elaboración propia.
La función diAlgoYAlgoMas recibe dos parámetros: una cadena de texto y una
callback. Esta callback (yAlgoMas) no es más que una función sencilla de tipo arrow,
que simplemente devuelve una cadena de texto fija. Con estos dos valores,
diAlgoYAlgoMas simplemente los empalma, pero fíjate que el segundo lo extrae de la
invocación de la callback (funcionCallback()).
El ejemplo anterior también contiene dos cosas reseñables del lenguaje
JavaScript.
Por un lado, si una función flecha no acepta parámetros, tenemos que seguir
indicando los paréntesis: let yAlgoMas = () => "y algo más!";.
Y la segunda cosa, y más importante, es que, si te has dado cuenta, la función
callback se define, en este caso, después de la función en la que es utilizada.
Esto debería llamarte la atención. Hasta ahora, siempre que usábamos algo (una
variable, constante, etc.) debía ser definido con antelación.
Desarrollo Web: Full Stack 16
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Casi todos los lenguajes de programación legendarios (C, C++, etc.) tienen este
requerimiento. Entonces, ¿por qué puede definirse la función yAlgoMas después?
Pues muy sencillo, por una cosa que se llama hoisting.
El hoisting implica que JavaScript se ocupa personal y automáticamente
de que las variables y funciones estén definidas antes, aunque hayamos
escrito su definición después.
Desarrollo Web: Full Stack 17
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.6. Funciones de orden superior
Las funciones de orden superior no son más que métodos que se aplican sobre
arrays, sets y mapas. Veamos las más importantes.
Recorrido de arrays
El método forEach(callback) recibe como único parámetro una función callback y
permite recorrer arrays de manera muy sencilla:
Figura 19. Recorrido de arrays con forEach. Fuente: elaboración propia.
En cada llamada de la callback (que tiene forma de función flecha en este caso), se
pasa el valor de un elemento concreto (matematico) y el índice que ocupa dentro del
array (indice). Con estos dos parámetros, forEach permite realizar operaciones sobre
cada elemento del array (matematicos).
Habrás podido comprobar que la función callback no tiene ningún nombre y no ha
sido definida previamente. Aparece sin nombre y directamente como parámetro del
método forEach(). A este tipo de funciones se las llama funciones anónimas.
Derivación de arrays
El método .map(callback) permite hacer algo parecido al forEach(), solo que, en cada
paso, el valor derivado a partir de cada elemento se añade a un nuevo array.
Figura 20. Derivación de arrays. Fuente: elaboración propia.
Desarrollo Web: Full Stack 18
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Filtrado de arrays
El método filter(callback) permite aceptar o rechazar los elementos de un array, los
cuales son testeados por la función callback, la cual los recibe uno a uno. Cada
prueba debe devolver true o false según se pase o no. Veamos un ejemplo que filtra
solo los números impares de un array que contiene, inicialmente, tanto impares como
pares.
Figura 21. Filtrado de arrays. Fuente: elaboración propia.
En la sección A fondo, Métodos sobre arrays, encontrarás un enlace a la
documentación de Mozilla que contiene muchos más métodos disponibles para
los arrays.
Desarrollo Web: Full Stack 19
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.7. Objetos literales
Todo dato en JavaScript tiene como tipo cualquiera de los siguientes:
▸ Los tipos básicos, como cadenas de texto, números, booleanos, símbolos,
▸ undefined y null.
▸ Los objetos como arrays, sets, mapas y objetos literales.
Los objetos literales no son más que conjuntos de propiedades y sus valores. Los
valores de las propiedades pueden ser a su vez cadenas de texto, números, etc. e
incluso otros objetos y funciones.
En el caso de que la propiedad tenga como valor una función, a esta se
la llama método.
Los objetos son como pequeñas bases de datos que contienen parejas de propiedad
y valor. En ese sentido, son parecidos a los mapas que vimos anteriormente. La
salvedad es que las propiedades son ahora solo cadenas de texto y sus valores
pueden ser cualquier cosa. También incorporan mecanismos interesantes, como el
encapsulamiento de código y la herencia, propios de la programación orientada a
objetos.
Los objetos literales suelen usarse para mantener información y
funcionalidad sobre esa información de manera cohesionada y en un
mismo lugar.
Desarrollo Web: Full Stack 20
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Definición de objetos de manera literal
Para definir un objeto usando la notación literal o directa, simplemente tenemos que
listar, entre llaves de bloque y separados por comas, parejas de propiedades y su
valor.
Ejemplo:
Figura 22. Declaración de objeto de forma literal. Fuente: elaboración propia.
En este ejemplo hemos definido un objeto (buzz) que tiene tres propiedades. Una de
ellas (nombre) es una cadena texto (tipo básico), otra es un array (amigos) y la otra
se corresponde con una función, escrita con notación de flecha. De igual manera, los
valores de las propiedades pueden estar almacenados externamente en variables o
constantes:
Figura 23. Almacenar propiedades en variables. Fuente: elaboración propia.
Desde ES6, se incorpora una nueva sintaxis resumida para definir objetos literales.
Esta consiste en que, si el nombre de la propiedad y el de la variable a la que se
refiere tienen el mismo nombre, basta con poner unas de las dos.
Desarrollo Web: Full Stack 21
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Es decir, basándonos en el ejemplo anterior, tendríamos:
Figura 24. Sintaxis alternativa de objetos literales. Fuente: elaboración propia.
En este ejemplo, hemos creado un objeto (rex) con una propiedad llamada nombre,
que recibe como valor el albergado en una variable con el mismo, valga la
redundancia, nombre.
Habrás podido comprobar que hemos estado creando objetos usando una notación
literal, de ahí que nos estemos refiriendo todo el tiempo a objetos literales.
Evidentemente, existe una notación de función constructora, pero que apenas es
utilizada:
Figura 25. Función constructora de objetos. Fuente: elaboración propia.
Métodos y propiedades
Es posible acceder a las propiedades de un objeto mediante la notación de punto
([Link]). Ejemplo:
Figura 26. Acceso a propiedades con notación de punto. Fuente: elaboración propia.
También es posible usar la notación de corchetes (objeto[propiedad]). Ejemplo:
Figura 27. Acceso a propiedades con notación de corchetes. Fuente: elaboración propia.
Desarrollo Web: Full Stack 22
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
De igual manera podemos ejecutar las funciones que se encuentran detrás de
algunas propiedades, es decir, podemos invocar métodos.
Ejemplo:
Figura 28. Acceso a métodos con notación de punto. Fuente: elaboración propia.
Como se trata de una función que queremos que se ejecute, tenemos que sufijar los
paréntesis de apertura y cierre. Es posible igualmente usar la notación de corchetes
que hemos visto antes:
Figura 29. Acceso a métodos con notación de corchetes. Fuente: elaboración propia.
¿Cómo podemos comprobar si un objeto tiene una propiedad? Para eso JavaScript
tiene el método hasOwnProperty(nombrePropiedad). Veamos un ejemplo:
Figura 30. Método hasOwnProperty. Fuente: elaboración propia.
O también podemos obtener la lista, en forma de array, de todas las propiedades de
un objeto con el método [Link](objeto). Ejemplo:
Figura 31. Método keys. Fuente: Elaboración propia
La versión ES8 (ojo, no ES6) que vio la luz en 2017 añade el método [Link]().
Desarrollo Web: Full Stack 23
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Este funciona de manera parecida al anterior, pero ahora devuelve un array con los
valores de estas propiedades:
Figura 32. Método values. Fuente: elaboración propia.
Modificación de objetos
No tenemos que conformarnos con el momento de definición de un objeto para dejar
claro con qué propiedades cuenta. En cualquier momento podemos añadir una
nueva propiedad de manera muy sencilla:
Figura 33. Añadir una propiedad a un objeto. Fuente: elaboración propia.
De igual manera, no hay problema en modificar el valor de una propiedad ya
existente:
Figura 34. Modificación de propiedades. Fuente: elaboración propia.
Eso sí, a la hora de borrar propiedades tenemos que usar un nuevo operador
llamado delete. Si queremos borrar una propiedad de un objeto, tenemos que
indicarlo con la siguiente sintaxis:
Figura 35. Eliminando propiedades. Fuente: elaboración propia.
Desarrollo Web: Full Stack 24
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Este método devuelve true o false según el éxito de la operación. Veamos un
ejemplo:
Figura 36. Eliminando propiedades 2 . Fuente: elaboración propia.
Objetos como parámetros
Evidentemente, no hay problema en pasar objetos como parámetros de funciones o
métodos. Sin embargo, hay que tener en cuenta que, a diferencia de los tipos
básicos, cuando un objeto es pasado como parámetro en una función, este pasa por
referencia.
Es decir, dentro de la función, seguimos teniendo acceso al objeto original y no a una
copia de este. Esta afirmación no vale para los datos básicos (cadenas de texto y
números).
Cuando pasamos un número o cadena de texto como parámetro a una
función, su valor se copia y la función maneja dicha copia.
El uso de objetos literales como parámetros de función tiene una utilidad muy
concreta en JavaScript, permite pasar a la función información etiquetada, en
cualquier orden y de manera muy limpia. Veamos un ejemplo:
Figura 37. Paso de argumentos. Fuente: elaboración propia.
Desarrollo Web: Full Stack 25
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.8. El objeto this
La palabra especial this en JavaScript usada dentro de, por ejemplo, un objeto, hace
referencia al propio objeto. Es, en cierta medida, equivalente al this de Java o al self
de Objective-C (muy usado hasta 2017 en la programación nativa en macOS e iOS).
Cuando ya tenemos una referencia al propio objeto (a sí mismo) podemos acceder a
sus propiedades y hacer cosas con ellas desde las funciones/métodos del propio
objeto:
Figura 38. Usando this. Fuente: elaboración propia.
En este ejemplo, el método tira() puede acceder a la propiedad metal contenida en sí
misma. Importante, para hacer referencia a this desde una función definida en un
objeto, tenemos que usar la notación habitual de funciones. Dicho de otra manera:
las funciones arrow no tienen acceso al objeto this.
Desarrollo Web: Full Stack 26
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.9 Promesas y funciones asíncronas
Las promesas son una nueva manera de llamar a las funciones callback. En ese
sentido, no añaden ninguna funcionalidad especial, pero simplifican el proceso
asíncrono como los de las funciones AJAX. Cuando una promesa se crea, esta
invoca una función asíncrona y al objeto promesa (sí, son objetos, como los
eventos) se queda en posición de espera hasta que esta termine.
Cuando esto ocurre, puede devolver:
▸ Resuelta: cuando la operación asíncrona se llevó a cabo satisfactoriamente.
▸ Rechazada: si la operación asíncrona tuvo algún problema.
El esqueleto en JavaScript de una promesa sería el siguiente:
Figura 39. Promesa en JavaScript. Fuente: elaboración propia.
La forma de marcar este éxito o no es mediante dos funciones: todoOK() y
algoFueMal(). Puedes comprobar por ti mismo como, a pesar de que las promesas
solucionan gran parte del código sucio del que eran culpables las callbacks, todavía
resultan un poco farragosas en términos de sintaxis.
Para simplificar todavía más la sintaxis, en la especificación de JavaScript de 2017
se añadieron las funciones asíncronas:
Desarrollo Web: Full Stack 27
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
▸ Este tipo de funciones están precedidas por la palabra clave async. Dentro de este
tipo de funciones podemos ejecutar código asíncrono como si fuera síncrono.
▸ En cada línea de esta función tenemos que spousar el operador await para marcar
una función como asíncrona.
▸ El valor devuelto se empaqueta como una promesa que puede almacenarse en
una variable. Las siguientes líneas de código no se ejecutan hasta que la promesa
se resuelve.
Esto se entenderá mejor con un ejemplo:
Figura 40. Async y await. Fuente: elaboración propia.
En las líneas anteriores, la función cargarUsuario está precedida por la palabra
reservada async, lo que implica que la función se ejecuta de manera asíncrona (es
decir, al mismo tiempo que el código restante del programa). Dentro de la función,
cada línea se ejecuta línea a línea y esto lo garantiza la palabra reservada await.
Desarrollo Web: Full Stack 28
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.10. Closures
Los closures (o cierres, aunque jamás se usa su traducción en español) son una de
las características más eficientes de JavaScript y de la programación funcional. Un
closure es una referencia a una variable que fue creada en el ámbito de otra función,
pero esta variable permanece accesible y puede ser usada en otra parte del
programa.
La principal característica de un closure es que una función interna es declarada
dentro de otra función y la primera tiene acceso al ámbito de la segunda.
Figura 41. Closure. Fuente: elaboración propia.
La función funcionExterna() solo tiene acceso a la variable variableExterna porque ha
sido declarada en su ámbito. La función funciónInterna(), por otro lado, tiene acceso
a ambas variables: variableExterna y variableInterna.
Esto implica que siempre que una función sea declarada dentro de otra
función, la función interna tendrá acceso a las variables que son
declaradas en la función externa.
Desarrollo Web: Full Stack 29
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
La potencia de los closures radica en que podemos definir una función que devuelve
otra función que tiene acceso a las variables de la primera. Esta potencia puede
usarse para generar lo que se conoce como fábricas de funciones.
Una fábrica de funciones es una función externa que permite crear funciones hijas
que son parecidas o tienen algún tipo de relación.
Veamos un ejemplo. Supongamos que queremos añadir la funcionalidad de convertir
entre distintas unidades de longitud. Es decir, queremos poder pasar de metros a
centímetros o de millas a kilómetros. Podríamos hacerlo con una fábrica de funciones
donde cada función fuese una transformación concreta de una unidad a otra:
Figura 42. Fábrica de funciones usando closures. Fuente: elaboración propia.
En el ejemplo anterior, con una sencilla fábrica de funciones hemos definido dos
funciones:
▸ Con la primera pasamos de metros a centímetros.
▸ Con la segunda pasamos de centímetros a metros.
Desarrollo Web: Full Stack 30
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.11. Código de apoyo y ejercicios
Recuerda que tienes a tu disposición todo el código de apoyo necesario para el
correcto seguimiento de las clases en el repositorio global de GitHub de la
asignatura, en la sección de Código de apoyo de este tema.
UnirCs (s. f.). DWFS-GLOBAL/Tema_3/Codigo de ejemplo at master ·
UnirCs/DWFS-GLOBAL. GitHub. [Link]
GLOBAL/tree/master/Tema_3/Codigo%20de%20ejemplo
Recuerda también que tienes a tu disposición los ejercicios de este tema en el
repositorio global de GitHub de la asignatura, en la sección de Ejercicios.
UnirCs (s. f.). DWFS-GLOBAL/Tema_3 at master · UnirCs/DWFS-GLOBAL.
GitHub. [Link]
Promesas con JavaScript
Utilizando la API de chistes de Chuck Norris, pondremos en práctica el uso de
promesas en JavaScript. En este ejercicio, trataremos de aunar algunos de los
conceptos que hemos ido trabajando en los tres primeros temas de la asignatura.
Concretamente:
▸ Crearemos un archivo HTML [Link] que contendrá, como mínimo, un botón con
el texto "Dame un chiste", que, cada vez que se presione, realizará una llamada
contra la API de chistes aleatorios de Chuck Norris, y volcará el chiste recibido en un
párrafo <p> del documento HTML.
▸ El script para realizar esta acción estará dentro del propio archivo HTML.
Desarrollo Web: Full Stack 31
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
▸ Eventos de JavaScript.
▸ Crearemos un archivo CSS [Link] que contendrá cualquier estilo que queramos
aplicar al documento HTML.
La petición asíncrona que debe realizarse para obtener los datos del chiste debe
realizarse mediante Fetch API, tal y como vimos en el ejemplo de clase. No
obstante, podéis obtener más información de esta API aquí. Se recomienda también
leer la documentación sobre Response, el objeto que recibimos tras utilizar fetch,
para averiguar cómo obtener el JSON de la respuesta recibida. La función JS
resultante puede codificarse de la forma que más te guste (mediante la palabra
reservada function o como una lambda/flecha). Será necesario encadenar promesas
para obtener el resultado deseado en el párrafo de nuestro documento HTML.
Por último, para actualizar de forma dinámica el contenido del párrafo, sin necesidad
de recargar la página web AJAX, haremos uso del método getElementById del
objeto document (el cual estudiaremos en el siguiente tema), por lo que será
necesario dotar de un id al párrafo cuyo valor queramos modificar. Recuerda que el
contenido HTML de un elemento es accesible a través de la propiedad innerHtml.
Debes consultar la documentación sobre el evento onClick para realizar este
ejercicio: [Link]. (s. f.).
[Link]
Desarrollo Web: Full Stack 32
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Ejemplo de resultado
Estado inicial del botón y párrafo:
Figura 43. Fuente: elaboración propia.
Hacemos clic en el botón 1 vez:
Figura 44. Fuente: elaboración propia.
Hacemos clic en el botón otra vez y sucesivas:
Figura 45. Fuente: elaboración propia.
Desarrollo Web: Full Stack 33
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Integración de HTML, CSS y JS
Continuamos con el ejercicio de la selección de butacas de un cine. Engancharemos
los ficheros construidos hasta el momento y aseguraremos que todo funciona
correctamente. En este caso, vamos a «enganchar» el fichero HTML que definía
nuestra sala del cine con el script que desarrollamos en el Tema 2.
Dependiendo de cada implementación, es posible que haya que hacer cambios en
uno o en ambos ficheros. En el próximo tema, veremos cómo hacer esto mismo de
una forma más elegante, que no implique alterar el código HTML.
El objetivo es que, cuando se introduzca un nuevo número de butacas a reservar, se
muestre en la consola del navegador el resultado de ejecutar la función suggest
que ya programamos, asumiendo que la sala está totalmente vacía. Siempre
deberían aparecer en el set resultado las butacas de la última fila, o vacío.
Para ello, debemos:
▸ En el fichero [Link] que desarrollamos en el Tema 1, incluir la referencia al
script [Link] que desarrollamos en el Tema 2. ¿Es la ejecución de este script
algo crítico para la carga de la página? ¿Debe estar dentro de ``head`` o al final de
``body`` ?
▸ Debes hacer una llamada a la función únicamente a modo de prueba, por ejemplo,
suggest(8) desde el HTML. La propia función debe tener un log que muestre el set
que se está devolviendo antes de terminar su ejecución. En el próximo tema,
haremos que esta llamada use un parámetro dinámico. Por ahora, la invocación
quedará fija.
Desarrollo Web: Full Stack 34
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
▸ La función debe ejecutarse cuando el contenido del input cambie. Para ello, debes
usar:
• El evento onInput del input en el archivo HTML. Aquí tienes más información sobre
este evento. Si bien podrían haberse usado otros eventos, como onChange , en este
caso, este evento es el más adecuado. Puedes probar las diferencias entre ambos si
quieres.
En el siguiente tema, veremos también herramientas para cambiar el estilo visual de
las butacas una vez hayan sido seleccionadas.
Ejemplo de resultado
Ten en cuenta que los resultados que se muestran en la consola en estos ejemplos
corresponden a una matriz de 10x10, tal como se daba en el código de apoyo del
Tema 2. Lo que se busca es ver que la conexión entre el archivo HTML y el JS
funciona correctamente.
Estado inicial:
Figura 46. Fuente: elaboración propia.
Desarrollo Web: Full Stack 35
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
Cambiamos contenido del input 1 vez:
Figura 47. Fuente: elaboración propia.
Cambiamos contenido del input otra vez y sucesivas:
Figura 48. Fuente: elaboración propia.
Desarrollo Web: Full Stack 36
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
Ideas clave
3.12. Referencias bibliográficas
AJAX - Aprende desarrollo web (2024, 6 junio). MDN Web Docs.
[Link]
side_web_APIs/Fetching_data
[Link] - Referencia de la API Web (s. f.). MDN Web Docs.
[Link]
Element: innerHTML property - Web APIs (2024, 26 julio). MDN Web Docs.
[Link]
Fetch API - Web APIs (2024, 8 octubre). MDN Web Docs.
[Link]
Página de Chuck Norris. [Link]
Response: json() method - Web APIs (2024, 8 octubre). MDN Web Docs.
[Link]
Pá[Link]. (s. f.). oninput Event.
[Link]
Desarrollo Web: Full Stack 37
Tema 3. Ideas clave
© Universidad Internacional de La Rioja (UNIR)
A fondo
Programación basada en eventos
Krishnakumar. (2017, enero 12). Learn Event Driven Programming in [Link].
E d u o n i x . [Link]
programming-node-js/
En este artículo se resume con detalle la programación orientada a eventos en
JavaScript.
Desarrollo Web: Full Stack 38
Tema 3. A fondo
© Universidad Internacional de La Rioja (UNIR)
A fondo
Métodos sobre arrays
Mdn web docs. (2021, junio 22). Array.
[Link]
y#
Esta página web muestra los métodos más usados sobre arrays.
Desarrollo Web: Full Stack 39
Tema 3. A fondo
© Universidad Internacional de La Rioja (UNIR)
Test
1. ¿Cómo podemos filtrar los contenidos de un array?
A. No es posible en JavaScript.
B. Con el método filter(), el cual acepta como parámetro el número mínimo de
elementos del array.
C. Con el método filter().
D. Con el método filter(), el cual acepta como parámetro el número máximo de
elementos del array.
2. ¿Qué devuelve [Link](objeto) ?
A. Undefined.
B. Un array que lista las propiedades del objeto como cadenas de texto.
C. Una cadena de texto con el número de propiedades del objeto.
D. Un objeto vacío y sin inicializar.
3. ¿Qué símbolo indica una arrow function?
A. La palabra reservada function.
B. =>.
C. Un tipo de bucle.
D. Ninguna de las anteriores.
4. ¿Qué es una función callback?
A. Una función llamada por otra función.
B. Una función justamente con ese nombre: callback().
C. Un método.
D. Una propiedad de un array de cuatro elementos.
Desarrollo Web: Full Stack 40
Tema 3. Test
© Universidad Internacional de La Rioja (UNIR)
Test
5. Los valores de las propiedades de un objeto:
A. Solo pueden ser números.
B. Solo pueden ser cadenas de texto.
C. Solo pueden ser otros objetos.
D. Todas las anteriores son falsas.
6. Para referenciar a this desde dentro de un objeto:
A. El objeto tiene que ser siempre un array.
B. Podemos usar una función definida por su nombre.
C. Es imposible.
D. Usamos el método definido como una función flecha.
7. Es imposible crear un objeto de manera no literal:
A. Verdadero.
B. Falso.
8. En JavaScript no hay parámetros por defecto en las funciones:
A. Verdadero.
B. Falso.
9. El número de parámetros de una función:
A. Puede ser variable.
B. Es siembre fijo e igual a 3.
C. Es siembre fijo e igual a 2.
D. Todas las afirmaciones anteriores son falsas.
Desarrollo Web: Full Stack 41
Tema 3. Test
© Universidad Internacional de La Rioja (UNIR)
Test
10. Los métodos forEach() y map() :
A. Hacen exactamente lo mismo.
B. Ambos devuelven valores derivados.
C. Son distintos.
D. Todas las afirmaciones anteriores son falsas.
Desarrollo Web: Full Stack 42
Tema 3. Test
© Universidad Internacional de La Rioja (UNIR)