0% encontró este documento útil (0 votos)
32 vistas697 páginas

Full Miraclelab Slides

Este documento proporciona una introducción a Node.js. Node.js es un entorno de tiempo de ejecución de JavaScript que usa el motor V8 de Chrome para ejecutar JavaScript fuera de un navegador. Node.js usa E/S asíncronas y no bloqueantes para manejar miles de conexiones simultáneas de forma eficiente con un solo proceso. También incluye npm, un sistema de paquetes que alberga más de un millón de paquetes de código abierto para Node.js.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
32 vistas697 páginas

Full Miraclelab Slides

Este documento proporciona una introducción a Node.js. Node.js es un entorno de tiempo de ejecución de JavaScript que usa el motor V8 de Chrome para ejecutar JavaScript fuera de un navegador. Node.js usa E/S asíncronas y no bloqueantes para manejar miles de conexiones simultáneas de forma eficiente con un solo proceso. También incluye npm, un sistema de paquetes que alberga más de un millón de paquetes de código abierto para Node.js.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 697

MiracleLab

MiracleLab
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Ultima actualización: July 26, 2022.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

1/697
Javascript

Javascript
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

2/697
Javascript

Historia

3/697
Historia

▶ Lenguaje de programación desarrollado por Brendan Eich


▶ Se creó en Netscape como una herramienta de secuencias de comandos para
manipular páginas Web en el navegador Netscape Navigator

4/697
Historia cont.

▶ Desde su lanzamiento en 1995, JavaScript ha pasado por muchos cambios


▶ Al comienzo sólo se utilizaba para agregar elementos interactivos o ”dar vida” a
las páginas web: clics en botones, eventos sobre enlaces, validación de formularios,
etc.
▶ Más tarde, JavaScript se hizo más robusto con DHTML y AJAX
▶ Hoy en día, con la aparición de Node.js, JavaScript se ha convertido en un
lenguaje que trascendió las fronteras del navegador Web para permitir crear
aplicaciones del lado del servidor o de escritorio
▶ Podemos usar JavaScript para programar robots (http://johnny-five.io/)
o crear herramientas de línea de comandos
(https://www.npmjs.com/package/commander)

5/697
Historia cont.

▶ La evolución ha sido guiada por un grupo de personas y de empresas que usan


JavaScript, proveedores de navegadores
▶ El comité a cargo de guiar los cambios en JavaScript a lo largo de los años es la
Asociación Europea de Fabricantes de Computadoras (ECMA)
▶ Los cambios en el lenguaje son impulsados por la comunidad
▶ Cualquiera puede presentar una propuesta al comité ECMA
▶ La responsabilidad del comité ECMA es administrar y priorizar estas propuestas
para decidir qué se incluye en cada especificación

6/697
Historia cont.

▶ El primer lanzamiento de ECMAScript fue en 1997, ECMAScript1


▶ Esto fue seguido en 1998 por ECMAScript2
▶ ECMAScript3 apareció en 1999, agregando expresiones regulares, manejo de
cadenas y más
▶ La versión ECMAScript4 nunca fue lanzada
▶ En 2009, se lanzó ECMAScript5 (ES5), que incorpora características nuevas como:
métodos de arreglos, propiedades de objeto y soporte de biblioteca para JSON

7/697
Historia cont.

▶ Después del lanzamiento de ES6 o ES2015 en 2015, la especificación ECMAScript


se ha movido a una cadencia de lanzamiento anual, y las versiones del lenguaje
ES2016, ES2017, ES2018, ES2019 y ES2020 ahora se identifican por año de
lanzamiento
▶ Todo lo que se proponga agregar y que formará parte de la especificación de
JavaScript se lo denomina ESNext
▶ En ES5 y versiones posteriores, los programas pueden optar por el modo estricto
de JavaScript en el que se han corregido una serie de errores de lenguaje iniciales
▶ ES6 se lanzó en 2015 y agregó nuevas características importantes, incluida la
sintaxis de clases y módulos

8/697
Más información

▶ Historia (https://en.wikipedia.org/wiki/JavaScript)
▶ Modo estricto (https://developer.mozilla.org/es/docs/Web/JavaScript/
Reference/Strict_mode)
▶ Transición a modo estricto
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/
Reference/Strict_mode/Transitioning_to_strict_mode)
▶ La guerra de los navegadores
(https://www.emezeta.com/articulos/browser-wars-la-historia-de-
la-guerra-de-navegadores)
▶ Estado de JS 2021 (https://2021.stateofjs.com/)
▶ El estado de Octoverse 2021 (https://octoverse.github.com/)

9/697
Javascript

Caracteristicas

10/697
Caracteristicas

▶ JavaScript es un lenguaje:
▶ Interpretado: Es un lenguaje de programación para el que la mayoría de sus
implementaciones ejecuta las instrucciones directamente, sin una previa compilación
del programa a instrucciones en lenguaje máquina
▶ Hilo único: Los lenguajes de programacion pueden ser de un único hilo o multi hilo.
JavaScript posee un único hilo de ejecución
▶ Tipado dinámico: Un lenguaje de programación tiene un sistema de tipos dinámico
cuando el tipo de dato de una variable puede cambiar en tiempo de ejecución. La
mayoría de los lenguajes de tipado dinámico son lenguajes interpretados
▶ Inferencia de tipos: Al decir a = 5 o a = "Hola mundo", JavaScript es capaz
de inferir el tipo de dato de una variable a partir del valor que se le está asignando

11/697
Introducción cont.

▶ Tipado débil: Un lenguaje se considera de tipado fuerte cuando ante una


operación entre dos tipos de datos incompatibles, arroja un error (durante la
compilación o la ejecución, dependiendo de si se trata de un lenguaje compilado o
interpretado), en lugar de convertir implícitamente alguno de los dos tipos
▶ Multiparadigma: La Programación Multiparadigma es una práctica que emerge
como resultado de la co-existencia de los paradigmas Orientado a Objetos,
Procedural, Declarativo y Funcional buscando mejorar la producción en el
desarrollo de proyectos. Según lo describe Bjarne Stroustrup, permiten crear
”programas usando más de un estilo de programación”

12/697
Más información

▶ Tipos en JavaScript (https:


//developer.mozilla.org/es/docs/Web/JavaScript/Data_structures)
▶ Paradigmas en JavaScript
(https://dev.to/alamin__yusuf/paradigms-in-javascript-1m31)
▶ Event loop en JavaScript (https://www.becomebetterprogrammer.com/is-
node-js-single-threaded-or-multi-threaded-and-why/)

13/697
Javascript

Node.js

14/697
Introducción

▶ Node.js es un entorno de tiempo de ejecución de JavaScript de código abierto


y multiplataforma
▶ Node.js ejecuta el motor V8 de JavaScript (que es el núcleo de Google Chrome)
fuera del navegador. Esto permite que Node.js sea muy eficaz
▶ Una aplicación en Node.js se ejecuta en un solo proceso, sin crear un nuevo hilo
para cada solicitud
▶ Node.js proporciona un conjunto de primitivas de E/S asincrónicas en su
biblioteca estándar que evita que el código JavaScript se bloquee
▶ En general, las bibliotecas en Node.js se escriben utilizando paradigmas que no
bloquean, lo que hace que el comportamiento de bloqueo sea la excepción en
lugar de la norma

15/697
Introducción cont.

▶ Cuando Node.js realiza una operación de E/S, como leer de la red, acceder a
una base de datos o al sistema de archivos, en lugar de bloquear el subproceso y
desperdiciar ciclos de CPU en espera, Node.js reanudará las operaciones cuando
regrese la respuesta
▶ Esto permite que Node.js maneje miles de conexiones simultáneas con un solo
servidor sin presentar la carga de administrar la concurrencia de subprocesos, lo
que podría ser una fuente importante de errores

16/697
Npm

▶ node.js cuenta con un gestor de paquetes llamado npm


▶ npm realiza dos tareas:
▶ Es un repositorio en línea para la publicación de proyectos Node.js de código abierto
▶ Es una utilidad de línea de comandos para interactuar con dicho repositorio que
ayuda en la instalación de paquetes, la gestión de versiones y la gestión de
dependencias
▶ npm con su estructura simple ayudó a que proliferar el ecosistema de Node.js
▶ El registro de npm alberga más de 1000000 de paquetes de código abierto que se
pueden usar libremente

17/697
Instalar Node.js

▶ Node.js se puede instalar de diferentes maneras


▶ Los paquetes oficiales para todas las plataformas principales están disponibles en
https://nodejs.dev/download/
▶ Una forma muy conveniente de instalar Node.js es a través de un administrador
de paquetes. En este caso, cada sistema operativo tiene el propio
▶ Otros administradores de paquetes para MacOS, Linux y Windows se enumeran
en https://nodejs.dev/download/package-manager/
▶ nvm (node version manager) es una forma popular de ejecutar Node.js
▶ Permite cambiar fácilmente la versión de Node.js e instalar nuevas versiones para
intentar revertir fácilmente cuando algo falla

18/697
Instalar Node.js cont.

▶ Una vez instalado tendrá acceso al programa ejecutable de Node.js en la línea de


comandos
▶ Si no está seguro de si Node.js está instalado en su máquina, puede abrir una
ventana de Terminal o Símbolo del sistema y escribir:
node -v

19/697
Diferencias entre Node.js y el Navegador

▶ Tanto el navegador como Node.js utilizan JavaScript como lenguaje de


programación
▶ La creación de aplicaciones que se ejecutan en el navegador es algo
completamente diferente a la creación de una aplicación Node.js
▶ A pesar de que en ambos casos se utiliza JavaScript, existen algunas diferencias
clave que hacen que la experiencia sea radicalmente diferente
▶ Las aplicaciones en Node.js traen consigo una gran ventaja: la comodidad de
programar todo, el frontend y el backend, en un solo lenguaje tanto en el cliente
como en el servidor

20/697
Diferencias entre Node.js y el Navegador cont.

▶ En el navegador, la mayoría de las veces se interactua con el DOM u otras API de


la plataforma web como las cookies. Esto no existe en Node.js
▶ En Nodejs no existen el document, window y todos los demás objetos que
proporciona el navegador
▶ En el navegador, no tenemos todas las buenas API que proporciona Node.js a
través de sus módulos, como la funcionalidad de acceso al sistema de archivos
▶ Otra gran diferencia en Node.js es el control sobre el entorno
▶ En comparación con el entorno del navegador, donde no puede darse el lujo de
elegir qué navegador usarán sus visitantes, esto es muy conveniente
▶ Esto significa que puede escribir todo el JavaScript ES6-7-8-9 moderno que
admite su versión de Node.js

21/697
Diferencias entre Node.js y el Navegador cont.

▶ Dado que JavaScript se mueve tan rápido, pero los navegadores pueden ser un
poco lentos para actualizar, a veces en la web se queda atascado con el uso de
versiones anteriores de JavaScript/ECMAScript
▶ Puede usar Babel para transformar su código para que sea compatible con ES5
antes de enviarlo al navegador, pero en Node.js, no necesitará eso
▶ Otra diferencia es que Node.js es compatible con los sistemas de módulos
CommonJS y ES (desde Node.js v12), mientras que en el navegador comenzamos
a ver que se implementa el estándar de módulos ES.
▶ En la práctica, esto significa que puede usar tanto require() como import en
Node.js, mientras que en el Navegador está limitado a import
▶ Referencia: https://nodejs.dev/learn

22/697
Recorrido por JavaScript

▶ Iniciamos node con el comando node:


Welcome to Node.js v16.14.2.
Type ".help" for more information.
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.editor Enter editor mode
.exit Exit the repl
.help Print this help message
.load Load JS from a file into the REPL session
.save Save all evaluated commands in this REPL session to a file

Press ^C to abort current expression, ^D to exit the repl


>

23/697
Hola Mundo

▶ Para probar bloques de código pequeños puede utilzar tanto el entorno interactivo
de nodejs o la consola de Navegador
▶ Para códigos más complejos puede utilzar directamente un editor de texto
▶ Desde allí, puede copiar y pegar en la consola de JavaScript o en una sesión de
Node, o puede guardar su código en un archivo (la extensión de nombre de
archivo tradicional para código JavaScript es .js) y luego ejecutar ese archivo de
código JavaScript con Node:
node snippet.js
▶ Si usa Node de manera no interactiva, no imprimirá automáticamente el valor del
código que ejecute

24/697
Más información

▶ Sitio Web de Node.js (https://nodejs.dev/)


▶ Npm (https://nodejs.org/en/knowledge/getting-started/npm/what-is-
npm/)
▶ Nvm (https://heynode.com/tutorial/overview-how-manage-nodejs-
locally/)

25/697
Javascript

Herramientas de desarrollo

26/697
Configuración mínima

▶ La forma más simple de probar algunas líneas de JavaScript es a través del


Navegador
▶ Para ello podemos utilizar las DevTools que vienen incorporadas con la mayoría
de los Navegadores
▶ Tambien podemos usar herramientas en linea como ser https://jsbin.com
▶ Otra opcion para probar el código en JavaScript es utilizar un servidor Web
▶ Una opción de servidor Web escrito JavaScript es http-server. El siguiente
comando permite instalar http-server en nuestra maquina
npm install http-server -g
▶ Luego, para iniciar el servidor, ejecutamos el comando http-server

27/697
DevTools

Tenemos distintas formas de acceder al DevTools:


▶ Vía menú: Más herramientas > Herramientas para desarrolladores
▶ Vía menú contextual: Click derecho en cualquier lugar de la página >
Inspeccionar
▶ Vía atajos de teclado:
▶ MacOS: Cmd + Alt + i
▶ Windows o Linux: Ctrl + Shift + i o F12

28/697
DevTools cont.

Dentro de las herramientas de desarrollo, encontraremos las siguientes secciones:


▶ Device: Permite previsualizar el comportamiento de una Web en distintas
resoluciones de pantalla. Muy útil para emular el comportamiento en móviles
▶ Elements: Permite acceder a los elementos que conforman a una página Web. Es
posible manipular los argumentos y de esa forma modificar contenido y estilos
▶ Console: Registra el contenido de logs de la Web y permite interactuar con ella y
con el código JS que contiene
▶ Sources: Permite depurar el código y conectarnos a nuestro sistema de archivos
para usar el depurador como un editor en tiempo real
▶ Network: Registra el detalle de cada petición y respuesta de un sitio Web.
Además, permite emular conexiones de red

29/697
DevTools cont.

▶ Performance: Permite grabar todos los eventos que ocurren durante el ciclo de
vida de un sitio Web
▶ Memory: Nos permite identificar memory leaks en nuestras aplicaciones. Nos
permite visualizar en tiempo real el consumo de Heap de una página
▶ Application: Aquí podemos consultar todos los recursos del navegador que utiliza
un sitio Web: cookies, IndexedDB, Service Workers, storages, etc.
▶ Security: Sirve para consultar el nivel de seguridad de un sitio web: HTTPS,
certificados, etc.
▶ Lighthouse: Nos permite realizar auditorías sobre un sitio Web: Performance,
SEO, Accesibilidad, PWA y mejores prácticas

30/697
La consola

▶ La consola es, quizás, la herramienta más sobre-utilizada para depurar código y


entender qué está pasando en él
▶ Hay que tener en cuenta que en entornos productivos hay que limitar al máximo
posible el uso de logs
// Comprueba que si aserción es verdadera
console.assert('Padre' > 'Hijo');

// Limpia la consola
console.clear();

// Lista de forma interactiva las propiedades de un objeto


console.dir(window);

// Muestra una representación HTML del objeto


console.dirxml(document.body);

31/697
La consola cont.

▶ Nos permite agrupar elementos


const hobbits = ['Frodo Bolsón', 'Bilbo Bolsón', 'Samsagaz Gamyi', 'Peregrin Tuk'];
// Permite agrupar diferentes valores
console.group('The Hobbits'); %// O groupCollapsed
hobbits.forEach(hobbit => console.log(hobbit));
// Indica el fin del grupo
console.groupEnd();

▶ También podemos medir el timpo que toma ejecutar un conjunto de sentencias

// Establece un contador y le da un identificador


// Muy útil para obtener métricas de rendimiento
console.time('Mide el tiempo de este bloque');
// código a medir el rendimiento
console.timeEnd('Mide el tiempo de este bloque');

32/697
La consola cont.

▶ Podemos crear tablas con información


const heroes = [
{ nombre: 'Bruce', apellidos: 'Wayne', identidad: 'Batman'},
{ nombre: 'Diana', apellidos: 'prince', identidad: 'WonderWoman' },
{ nombre: 'Clark', apellidos: 'Kent', identidad: 'Superman' }
];

// Nos permite ver de forma muy visual el contenido de un array de objetos


console.table(heroes);

// Además permite filtrar que columnas visualizar


console.table(heroes, ['identidad']);

33/697
La consola cont.

▶ La consola está orientada a funcionar por niveles


▶ Existen cuatro categorías de salida que se pueden generar, utilizando los métodos:
▶ console.debug: Texto en color negro sin icono
▶ console.info: Texto de color azul con icono
▶ console.warn: Texto de color amarillo con icono
▶ console.error: Texto de color rojo con icono
▶ Cada uno de ellos muestran resultados que lucen diferentes en el registro
▶ Se pueden utilizar los controles de filtro del navegador para ver únicamente los
tipos de salida de interés

34/697
La consola cont.

▶ Esto, bien usado, es muy útil cuando queremos monitorear el estado de nuestro
código
// Muestra el mensaje sólo cuando lo forzamos
console.debug('Soy tímido')

// Saca un mensaje por consola


console.log('We love you console.log!');

// Muestra un mensaje informativo


console.info('A ti también console.info...');

// Muestra una advertencia por consola


console.warn('Hay que lavarse las manos y estornudar en el codo');

// Muestra un error por consola


console.error('Batman vs Superman');

35/697
La consola cont.
▶ No hay que olvidar que la consola, además de util, puede ser tan bonita como
queramos
▶ Además, algo que la diferencia de otras funciones de JavaScript, es que admite
”placeholding” de variables de forma nativa
%s Cadena de texto
%d / %i Entero
%f Decimal
%o DOM
%O Objeto JS
%c CSS
const parrafos = document.getElementsByTagName('p');
console.log('DOM: %o', parrafos);

const estilos = 'background: #00b5ac; color: #fff; font-size: 18px;';


const egocentrico = { 'nombre': 'Yo', 'Apellido': 'Mismo' };

console.log('%c Objeto: %O', estilos, egocentrico);


36/697
La consola cont.

▶ También podemos usar console.log('num: ', num) en lugar de


console.log('num: ' + num)
▶ Mientras que con el uso del + va a concatenar el resultado en una sola cadena, el
uso de la , nos permite agregar una descripción y también visualizar el contenido
de la variable en caso de que sea un objeto

37/697
Javascript

Variables

38/697
Declaracion de variables

▶ Antes de ES2015, la única forma de declarar variables era utilizando la palabra


clave var
▶ Ahora tenemos distintas opciones que mejoran la funcionalidad:
▶ La palabra clave const
▶ La palabra clave let
▶ Son case sensitive, es decir, las mayúsuculas son importantes

39/697
Reglas sintácticas

var variable1;
let variable2;
const variable3 = 2;

// puede contener letras, números, _ o $


var $jquery, _private;

// No puede empezar con números o contener espacios


var 50cent = 1, esto no vale = 1;

// Son case sensitive


var variable = 2, VARIABLE = 2;
// Mayoritariamente se usa camelCase, pero también se usa snake_case
var camelCase = 2, snake_case = 2;
// Se recomienda declarar una variable por línea
var camelCase = 2;
var snake_case = 3;

40/697
La palabra clave const

▶ Una constante es una variable que no puede ser reemplazada. Una vez declarada,
no es posible cambiar su valor
▶ JavaScript introdujo constantes en ES6
▶ Antes de las constantes, disponiamos solo de variables, las cuales pueden cambiar
su contenido:
var pizza = true;
pizza = false;
console.log(pizza); // false
▶ Si intentamos cambiar el valor de una constante va a generar un error por consola:

const pizza = true;


pizza = false; // Uncaught TypeError: Assignment to constant variable

41/697
La palabra clave let

▶ JavaScript posee ahora variables de alcance lexico


▶ En JavaScript podemos crear bloques de código utilizando llaves
▶ En funciones, dichas llaves limitan el alcance de cualquier variable declarada con
var
▶ Por otro lado, consideremos las sentencias if/else
▶ Si tenemos en mente otros lenguajes, podemos asumir de que estos bloques
también van a bloquear el alcance de la variable
▶ Este no es el caso, hasta que llego let

42/697
La palabra clave let cont.

▶ Si una variable se define dentro de un bloque if/else, dicha variable no queda


limitada solamente a dicho bloque:
var topic = 'JavaScript';
if (topic) {
var topic = 'React';
console.log('block', topic); // block React
}
console.log('global', topic); // global React
▶ La variable topic dentro del bloque, limpia el valor de topic fuera del bloque

43/697
La palabra clave let cont.

▶ Con la palabra clave let, podemos delimitar el alcance de una variable al bloque
de código donde fue declarada
▶ Usando let protejemos el valor de la variable global
var topic = 'JavaScript';
if (topic) {
let topic = 'React';
console.log('block', topic); // block React
}
console.log('global', topic); // global JavaScript
▶ El valor de topic fuera del bloque no se modifica

44/697
Alcance de las variables

▶ El alcance se refiere a desde dónde es accesible una variable dentro de un


algoritmo (también puede ser una función cuando trabajamos con ámbitos de
función)
▶ Hay variables locales y globales
var myVariable = 'global';
myOtherVariable = 'global';
function myFunction() {
var myVariable = 'local';
return myVariable;
}
function myOtherFunction() {
myOtherVariable = 'local';
return myOtherVariable;
}
console.log(myVariable); // global
console.log(myFunction()); // local
console.log(myOtherVariable); // global
console.log(myOtherFunction()); // local
console.log(myOtherVariable); // local

45/697
Alcance de las variables cont.

▶ En las estructuras de repeción las llaves no bloquean el alcance de una variable:

var div, container = document.getElementById('container');


for (var i = 0; i < 5; i++) {
div = document.createElement('div');
div.onclick = function() {
alert('This is box #' + i);
};
container.appendChild(div);
}

46/697
Javascript

Tipos

47/697
Tipos

▶ Los tipos de datos disponibles en JavaScript son los siguientes:


▶ undefined
▶ Object
▶ boolean
▶ number
▶ string
▶ Function
▶ symbol (ES6)

48/697
Tipos cont.

▶ Para conocer el tipo de una variable, tenemos dos opciones:


// como obtener el tipo de una variable
typeof variable;
// comprobar el tipo de una variable
variable instanceof Clase;

// undefined
typeof undefined;
typeof estaVariableQueNoHeInicializadoAun;

// object
typeof null;
typeof { key: 2 };
typeof [15, 4];
typeof new Date();

// boolean
typeof true;
typeof false;
typeof new Boolean(true);

49/697
Tipos cont.

// string
typeof 'hola';

// function
typeof function (){};

// number
typeof 1;
typeof 1.3;
typeof NaN;
typeof Infinity;

// symbol
typeof Symbol();
typeof Symbol('mi simbolo');

50/697
Objetos y arreglos

▶ Desde ES2016, la sintaxis de JavaScript ha admitido formas creativas para operar


sobre el contendido de los objetos y de los arreglos:
▶ Desestructuración de objetos
▶ Desestructuración de Arrays
▶ Mejora de objetos literales
▶ El operador de propagación

51/697
Desestructuración de objetos

▶ La desestructuración por asignacion permite acceder localmente a los campos


dentro de un objeto y declarar que valores se utilizaran
▶ Considere el objeto sandwich. Tiene cuatro propiedades, pero solo queremos usar
dos de ellas. Podemos buscar bread y meat para ser utilizadas localmente:
const sandwich = {
bread: 'dutch crunch',
meat: 'tuna',
cheese: 'swiss',
toppings: ['lettuce', 'tomato', 'mustard']
};

const { bread, meat } = sandwich;

console.log(bread, meat); // dutch crunch tuna


▶ El código extrae bread y meat del objeto y crea variables locales

52/697
Desestructuración de objetos cont.

▶ También podemos desestructurar los argumentos de funciones


▶ Considere una función que registraría el nombre de una persona como lord:
const lordify = function (regularPerson) {
console.log(regularPerson.firstname + ' of Canterbury');
};

const regularPerson = {
firstname: 'Bill',
lastname: 'Wilson'
};

lordify(regularPerson); // Bill of Canterbury

53/697
Desestructuración de objetos cont.

▶ En lugar de usar la sintaxis notación punto para acceder a las propiedades de los
objetos, podemos desestructurar los valores que necesitamos de regularPerson:

const lordify = function ({ firstname }) {


console.log(firstname + ' of Canterbury');
};
const regularPerson = {
firstname: 'Bill',
lastname: 'Wilson'
};
lordify(regularPerson); // Bill of Canterbury

54/697
Desestructuración de objetos cont.

▶ En el siguiente ejemplo, el objeto regularPerson tiene un objeto anidado en la


propiedad spouse:
const regularPerson = {
firstname: 'Bill',
lastname: 'Wilson',
spouse: {
firstname: 'Phil',
lastname: 'Wilson'
}
};

55/697
Desestructuración de objetos cont.

▶ Si quisiéramos hacer lord el nombre de spouse, deberíamos ajustar los


argumentos desestructurados de la función:
const lordify = function ({ spouse: { firstname } }) {
console.log(firstname + ' of Canterbury');
};
lordify(regularPerson); // Phil of Canterbury

56/697
Desestructuración arreglos

▶ Los valores también se pueden desestructurar a partir de arreglos


▶ Podemos asignar el primer valor de un arreglo a un nombre de variable
const [firstAnimal] = ['Horse', 'Mouse', 'Cat'];

console.log(firstAnimal); // Horse
▶ También podemos pasar por alto valores innecesarios con la coincidencia de
posiciones usando comas
▶ La coincidencia de posiciones ocurre cuando las comas reemplazan a los elementos
que deben omitirse
▶ Usando el mismo ejemplo anterior, podemos acceder al último valor reemplazando
los dos primeros valores con comas:
const [, , thirdAnimal] = ['Horse', 'Mouse', 'Cat'];

console.log(thirdAnimal); // Cat

57/697
Mejora de objetos literales

▶ La mejora de objetos literales es lo opuesto a la desestructuración


▶ Es el proceso de reestructurar o volver a armar el objeto
▶ Por ejemplo, podemos tomar variables del alcance global y agregarlas a un objeto:

const name = 'Tallac';


const elevation = 9738;

const funHike = { name, elevation };

console.log(funHike); // {name: 'Tallac', elevation: 9738}


▶ name y elevation ahora son propiedades del objeto funHike

58/697
Mejora de objetos literales cont.

▶ También podemos crear métodos de objetos con mejora o reestructuración de


objetos literales:
const name = 'Tallac';
const elevation = 9738;
const print = function() {
console.log('Mt. ' + this.name + ' is ' + this.elevation + ' feet tall');
};

const funHike = { name, elevation, print };

funHike.print(); // Mt. Tallac is 9738 feet tall

59/697
Mejora de objetos literales cont.

▶ Al definir métodos de objetos, ya no es necesario usar la palabra clave de


function:
// Antes
var skier = {
name: name,
sound: sound,
powderYell: function() {
var yell = this.sound.toUpperCase();
console.log(yell + ' ' + yell + ' ' + yell + '!!!');
},
speed: function(mph) {
this.speed = mph;
console.log('speed:', mph);
}
};

60/697
Mejora de objetos literales cont.

// Ahora
const skier = {
name,
sound,
powderYell() {
let yell = this.sound.toUpperCase();
console.log(yell + ' ' + yell + ' ' + yell + '!!!');
},
speed(mph) {
this.speed = mph;
console.log('speed:', mph);
}
};

61/697
El operador de propagación

▶ El operador de propagación (...) nos permite realizar varias tareas diferentes


▶ Podemos utilizarlo para combinar el contenido de arreglos
▶ Por ejemplo, si tuviéramos dos arreglos, podríamos hacer un tercer arreglo que
combine los dos arreglos en uno:
const peaks = ['Tallac', 'Ralston', 'Rose'];
const canyons = ['Ward', 'Blackwood'];
const tahoe = [...peaks, ...canyons];

console.log(tahoe); // [ 'Tallac', 'Ralston', 'Rose', 'Ward', 'Blackwood' ]

62/697
El operador de propagación cont.

▶ Usando el arreglo peaks del ejemplo anterior, imaginemos que queremos tomar el
último elemento del arreglo en lugar del primero
▶ Podríamos usar el método Array.reverse para invertir el arreglo en combinación
con la desestructuración de la matriz
const peaks = ['Tallac', 'Ralston', 'Rose'];
const [last] = peaks.reverse();

console.log(last); // Rose
console.log(peaks); // [ 'Rose', 'Ralston', 'Tallac']
▶ La función reverse en realidad ha alterado o mutado el arreglo

63/697
El operador de propagación cont.

▶ Utilizando el operador de propagación, no tenemos que mutar el arreglo original.


En su lugar, podemos crear una copia de la matriz y luego invertirla:
const peaks = ['Tallac', 'Ralston', 'Rose'];
const [last] = [...peaks].reverse();

console.log(last); // Rose
console.log(peaks); // [ 'Tallac', 'Ralston', 'Rose' ]
▶ Dado que usamos el operador de propagación para copiar el arreglo, el arreglo
peaks queda intacto y se puede usar más adelante en su forma original

64/697
El operador de propagación cont.

▶ El operador de propagación también se puede usar para obtener los elementos


restantes del arreglo:
const lakes = ['Donner', 'Marlette', 'Fallen Leaf', 'Cascade'];

const [first, ...others] = lakes;

console.log(others); // [ 'Marlette', 'Fallen Leaf', 'Cascade' ]

65/697
El operador de propagación cont.

▶ También podemos usar la sintaxis de tres puntos para agrupar los argumentos de
una función como un arreglo
▶ Ejemplo: la siguiente función toma una cantidad n de argumentos usando el
operador de propagación, luego usa esos argumentos para imprimir algunos
mensajes de la consola:
function directions(...args) {
let [start, ...remaining] = args;
let [finish, ...stops] = remaining.reverse();

console.log('drive through ' + args.length + ' towns');


console.log('start in ' + start);
console.log('the destination is ' + finish);
console.log('stopping ' + stops.length + ' times in between');
}

directions('Truckee', 'Tahoe City', 'Sunnyside', 'Homewood', 'Tahoma');

66/697
El operador de propagación cont.

▶ El operador de propagación también se puede usar para objetos


const morning = {
breakfast: 'oatmeal',
lunch: 'peanut butter and jelly'
};

const dinner = 'mac and cheese';

const backpackingMeals = {
...morning,
dinner
};

console.log(backpackingMeals);

// {
// breakfast: 'oatmeal',
// lunch: 'peanut butter and jelly',
// dinner: 'mac and cheese'
// }

67/697
Javascript

Control de flujo

68/697
Control de flujo

▶ Los programas en JavaScript son un conjunto de sentencias que se van a ejecutar


▶ De forma predeterminada, el intérprete de JavaScript ejecuta estas sentencias de
forma secuencial (una tras otra en el orden en que se escriben)
▶ Para alterar este orden de ejecución predeterminado, JavaScript tiene una serie de
sentencias o estructuras de control:
▶ Condicionales: sentencias como if y switch hacen que el intérprete de JavaScript
ejecute u omita otras sentencias dependiendo del valor de una expresión
▶ Repetición: sentencias como while y for ejecutan otras sentencias repetitivamente
▶ Saltos: sentencias como break, return y throw hacen que el intérprete salte a
otra parte del programa

69/697
Estructuras condicionales

▶ Las sentencias condicionales ejecutan u omiten otras sentencias según el valor de


una expresión específica
▶ Estas sentencias son los puntos de decisión dentro del código y, a veces, también
se conocen como ”ramas”.

70/697
Sentencia if

▶ La sentencia if es la sentencia de control fundamental que permite a JavaScript


tomar decisiones o, más precisamente, ejecutar sentencias condicionalmente
▶ Esta declaración tiene dos formas. La primera es:
if (expresion)
sentencia
▶ Se evalúa la expresión y si el valor resultante es verdadero, se ejecuta la instrucción
▶ Si la expresión es falsa, la sentencia no se ejecuta
if (username == null) // Si el username es null o undefined,
username = 'John Doe'; // lo definimos

71/697
Sentencia if cont.

▶ Los paréntesis alrededor de la expresión son una parte necesaria de la sintaxis de


la instrucción if
▶ La sintaxis de JavaScript requiere una sentencia única después de la palabra clave
if
▶ Se puede usar un bloque de sentencias para combinar varias sentencias en una
▶ La segunda forma de la sentencia if introduce una cláusula else que se ejecuta
cuando expresión es falsa
▶ Su sintaxis es:
if (expresion)
sentencia1
else
sentencia2
▶ En este caso la sentencia if ejecuta la sentencia1 si la expresión es verdadera y
ejecuta la sentencia2 si la expresión es falsa

72/697
Sentencia else if

▶ La sentencia if/else evalúa una expresión y ejecuta uno de dos fragmentos de


código, según el resultado
▶ ¿Qué pasa cuando es necesario ejecutar uno de muchos bloques de código?
▶ Una forma de hacer esto es con una sentencia else if
if (n === 1) {
// bloque de codigo #1
} else if (n === 2) {
// bloque de codigo #2
} else if (n === 3) {
// bloque de codigo #3
} else {
// Si todo lo anterior es falso, bloque de codigo #4
}

73/697
Sentencia switch

▶ Como vimos, se puede usar el idioma else if para realizar una bifurcación
multidireccional
▶ Esta no es la mejor solución cuando todas las ramas dependen del valor de una
misma expresión
▶ En ese caso, es un desperdicio evaluar repetidamente esa expresión en múltiples
sentencias if
▶ La instrucción switch maneja exactamente esta situación
▶ La palabra clave switch va seguida de una expresión entre paréntesis y un bloque
de código entre llaves
switch (expresion) {
sentencias
}

74/697
Sentencia switch cont.

▶ Varios lugares en el bloque de código están etiquetadas con la palabra clave case
seguida de una expresión y dos puntos
▶ Cuando se ejecuta switch, calcula el valor de expresión y luego busca una
etiqueta case cuya expresión evalúe como el mismo valor (donde la uniformidad
está determinada por el operador ===)
▶ Si encuentra uno, comienza a ejecutar el bloque de código en la declaración
etiquetada case
▶ Si no encuentra un case con un valor coincidente, busca una declaración
etiquetada como default
▶ Si no hay una etiqueta default, la sentencia switch omite el bloque de código
por completo

75/697
Sentencia switch cont.

switch(n) {
case 1:
// Codigo del bloque 1
break;
case 2:
// Codigo del bloque 2
break;
case 3:
// Codigo del bloque 3
break;
default:
// Codigo del bloque 4
break;
}

76/697
Sentencias de repetición

▶ Las sentencias de repetición son aquellas que desvían el flujo de ejecucion sobre sí
mismo para repetir partes de su código
▶ JavaScript tiene cinco sentencias de repeticion:
▶ while
▶ do/while
▶ for
▶ for/of (con su variante for/await)
▶ for/in

77/697
Sentencia while

▶ la instrucción while es la estructura de repeticion básica de JavaScript


▶ Tiene la siguiente sintaxis:
while (expresion)
sentencia
▶ Para ejecutar una instrucción while, el intérprete primero evalúa la expresión
▶ Si el valor de la expresión es falso, el intérprete se salta la sentencia que sirve
como cuerpo del ciclo y pasa a la siguiente sentencia en el programa
▶ Si, por el contrario, la expresión es verdadera, el intérprete ejecuta la sentencia,
saltando nuevamente a la parte superior del bucle, evaluando la expresión de nuevo

78/697
Sentencia do/while

▶ El ciclo do/while es como el ciclo while, excepto que la expresión del ciclo se
prueba en la parte inferior del ciclo en lugar de en la parte superior
▶ Esto significa que el cuerpo del bucle siempre se ejecuta al menos una vez
▶ La sintaxis es:
do
sentencia
while (expresion);
▶ El ciclo do/while se usa con menos frecuencia que su primo while

79/697
Sentencia do/while cont.
▶ ¿Cual es la diferencia entre while y do/while?

80/697
Sentencia for
▶ La mayoría de las estructuras de repeticion tienen una variable contador de algún
tipo
▶ Esta variable se inicializa antes de que comience la estructura de repeticion y se
verifica antes de cada iteración del ciclo
▶ Finalmente, la variable de contador se incrementa o se actualiza de alguna manera
al final del cuerpo del ciclo, justo antes de que la variable se vuelva a probar
▶ En este tipo de estructura de repeticion, la inicialización, la verificación y la
actualización son las tres manipulaciones cruciales de una variable de bucle
▶ La declaración for codifica cada una de estas tres manipulaciones como
expresiones y convierte esas expresiones en una parte explícita de la sintaxis del
bucle:
for (inicializacion; prueba; incremento)
sentencia
▶ inicialización, verificación e incremento son tres expresiones (separadas por punto
y coma) que son responsables de inicializar, probar e incrementar la variable de
ciclo respectivamente
81/697
Sentencia for cont.

▶ La forma más sencilla de explicar cómo funciona la estructura for es mostrar la


estructura while equivalente
inicializacion;
while (prueba) {
sentencia;
incremento;
}
▶ A veces múltiples variables cambian con cada iteración del ciclo
▶ Esta situación es el único lugar donde el operador coma se usa comúnmente en
JavaScript

82/697
Sentencia for cont.

▶ Proporciona una forma de combinar múltiples expresiones de inicialización e


incremento en una sola expresión adecuada para usar en una estructura for
let i, j, sum = 0;
for (i = 0, j = 10; i < 10; i++, j--) {
sum += i * j;
}
▶ Cualquiera de las tres expresiones puede omitirse de un ciclo for, pero se requieren
los ;
▶ Si omite la expresión de verificación, el ciclo se repite por siempre
▶ for(;;) es otra forma de escribir un ciclo infinito, como while(true)

83/697
Sentencia for cont.

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


console.log(i)
}

// a veces nos olvidamos que también es posible decrementar


for (let i = 10; i > 0; i -= 1) {
console.log(i)
}

// las expresiones en for no tienen por qué ser individuales


for (let i = 10, j = 0; i > j; i -= 1) {
console.log(i, j)
}

84/697
Sentencia for/of

▶ ES6 define una nueva instrucción de repeticion: for/of


▶ Este nuevo tipo utiliza la palabra clave for, pero es un tipo de estructura de
repeticion completamente diferente al bucle for normal
▶ El bucle for/of funciona con objetos iterables:
▶ arreglos
▶ strings
▶ Set
▶ Map
▶ Podemos usar for/of para recorrer los elementos de un arreglo de números y
calcular su suma:
let data = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], sum = 0;
for (let element of data) {
sum += element;
}

85/697
Sentencia for/of con objetos

▶ Los objetos no son (por defecto) iterables


▶ Intentar usar for/of en un objeto regular arroja un TypeError en tiempo de
ejecución:
let o = { x: 1, y: 2, z: 3 };
for (let element of o) { // Throws TypeError because o is not iterable
console.log(element);
}
▶ Si desea iterar a través de las propiedades de un objeto, puede usar la estructura
for/of con Object.keys()
let o = { x: 1, y: 2, z: 3 };
let keys = '';
for (let k of Object.keys(o)) {
keys += k;
}

86/697
Sentencia for/of con cadenas

▶ Si estámos interesados tanto en las claves como en los valores de las propiedades
de un objeto, podemos usar for/of con Object.entries() y la asignación de
desestructuración:
let pairs = '';
for (let [k, v] of Object.entries(o)) {
pairs += k + v;
}
▶ Object.entries() devuelve un arreglo de arreglos, donde cada arreglo interno
representa un par clave/valor para una propiedad del objeto
▶ Usamos la asignación de desestructuración en este ejemplo de código para
desempaquetar esos arreglos internos en dos variables individuales

87/697
Sentencias for/of con cadenas

▶ Las cadenas son iterables carácter por carácter en ES6:


let frequency = {};
for (let letter of 'mississippi') {
if (frequency[letter]) {
frequency[letter]++;
} else {
frequency[letter] = 1;
}
}
▶ Las cadenas se iteran por el código Unicode, no por carácter UTF-16

88/697
Sentencia for/of con Set y Map

▶ Las clases integradas de ES6 Set y Map son iterables


▶ Cuando itera un Set con for/of, el cuerpo del bucle se ejecuta una vez para
cada elemento del conjunto
▶ Se podría usar un código como el siguiente para imprimir las palabras únicas en
una cadena de texto:
let text = 'Na na na na na na na na Batman!';
let wordSet = new Set(text.split(' '));
let unique = [];
for (let word of wordSet) {
unique.push(word);
}

89/697
Sentencia for/of con Set y Map cont.

▶ Los Map son un caso interesante porque el iterador de un objeto Map no itera las
claves del mapa o los valores del mapa, sino los pares clave/valor
▶ Cada vez que se realiza la iteración, el iterador devuelve una matriz cuyo primer
elemento es una clave y cuyo segundo elemento es el valor correspondiente
▶ Dado un Map m, podría iterar y desestructurar su clave/valor pares como este:

let m = new Map([[1, 'one']]);


for (let [key, value] of m) {
key
value
}

90/697
Sentencia for/in

▶ Un bucle for/in se parece mucho a un bucle for/of


▶ Mientras que un bucle for/of requiere un objeto iterable después de of, un bucle
for/in funciona con cualquier objeto después de in
▶ El bucle for/of es nuevo en ES6, pero for/in ha sido parte de JavaScript desde
el principio (es por eso que tiene una sintaxis que suena más natural)
▶ La instrucción for/in recorre los nombres de propiedad de un objeto específico.
La sintaxis se ve así:
for (variable in objeto)
sentencia

91/697
Sentencia for/in

▶ Variable es la declaración de una variable


▶ Objeto es una expresión que se evalúa como un objeto
▶ Sentencia es la sentencia o bloque de sentencias que sirve como cuerpo del bucle

for(let p in o) { // Asignar nombres de propiedades de o a la variable p


console.log(o[p]); // Imprimir el valor de cada propiedad
}

92/697
Operador ternario

▶ <condición lógica> ? true : false


let edad = prompt('¿Cuantos años tienes?', 0);
▶ Aquí se modifica el mensaje en base a la variable edad
const mensaje = edad >= 18 ? 'Perfecto, puedes conducir' : 'No puedes conducir!';
▶ Se pueden ejecutar múltiples expresiones. No es nada recomendable, pero poder,
se puede :-)
let mensaje, edad = prompt('¿Cuantos años tienes?', 0);
edad >= 18 ? (
mensaje = 'Perfecto, puedes pasar',
console.log(mensaje)
) : (
mensaje = 'No vayas tan rápido!',
alert(mensaje)
);

93/697
Javascript

Características adicionales

94/697
Plantillas de cadena

▶ En ES6 se introdujeron las plantillas de cadena


▶ Las características de esta funcionalidad son:
▶ Variables dentro de cadenas (sin necesidad de ser concatenadas con +) y
▶ Cadenas de múltiples líneas

95/697
Variables dentro de cadenas

▶ A esta caracteristica se la llama también ”interpolación de cadenas”


▶ La idea es poder poner variables dentro de las cadenas:
var firstName = 'Nate';
var lastName = 'Murray';

// interpolamos una cadena


var greeting = `Hello ${firstName} ${lastName}`;

console.log(greeting);

96/697
Cadenas de múltiples líneas

▶ Las cadenas de múltiples líneas son un recurso valioso cuando necesitamos poner
cadenas dentro de nuestros templates
▶ Ejemplo:
var template = `
<div>
<h1>Hello</h1>
<p>This is a great website</p>
</div>
`

97/697
Javascript

Funciones

98/697
Creando funciones

▶ Cada vez que deseamos realizar algún tipo de tarea repetible con JavaScript,
podemos usar una función
▶ Algunas de las diferentes opciones de sintaxis que se pueden usar para crear una
función son las siguientes:
▶ Declaraciones de funciones
▶ Expresiones de función
▶ Función flecha

99/697
Declaraciones de funciones

▶ La declaración o definición de una función comienza con la palabra clave


function, seguida del nombre de la función
▶ Las sentencias JavaScript que forman parte de la función se definen entre llaves

function logCompliment() {
console.log("You're doing great!");
}
▶ Una vez definida la función, se invocará o llamará utilizando el nombre que se le
asignó:
logCompliment();

100/697
Expresiones de función

▶ En este caso solo implica crear la función como una variable:


const logCompliment = function() {
console.log("You're doing great!");
};
logCompliment();

101/697
Declaraciones de funciones frente a expresiones

▶ Algo a tener en cuenta al decidir entre una declaración de función y una expresión
de función es que las declaraciones de función se elevan mientras que las
expresiones de función no
▶ Por lo tanto, puede invocar una función antes de escribir la declaración de la
función
// Invocando la función antes de que sea declarada
hey();
// Declaración de la función
function hey() {
alert("hey!");
}
▶ Esto funciona dado que la función se eleva o sube a la parte superior del alcance
del archivo

102/697
Declaraciones de funciones frente a expresiones cont.

▶ No es posible invocar una función creada por una expresión de función antes de la
expresión
▶ Si probamos el mismo ejercicio con una expresión de función causará un error:

// Invocando la función antes de que sea declarada


hey();
// Expresión de función
const hey = function() {
alert("hey!");
};
TypeError: hey is not a function
▶ Obviamente, este es un pequeño ejemplo, pero este TypeError puede surgir
ocasionalmente al importar archivos y funciones en un proyecto

103/697
Pasaje de argumentos

▶ Si queremos proporcionar variables dinámicas a la función, podemos pasar


parámetros con nombre a una función simplemente agregándolos a los paréntesis
▶ Comencemos agregando una variable firstName:
const logCompliment = function(firstName) {
console.log("You're doing great, " + firstName);
};
logCompliment("Molly");
▶ Ahora, cuando llamamos a la función logCompliment, el valor firstName
enviado como argumento se agregará al mensaje de la consola

104/697
Retorno de funciones

▶ La función logCompliment utiliza la consola para visualizar un mensaje


▶ En general una mejor práctica es definir una función que devuelva un valor
▶ Una declaración de return especifica el valor retornado por la función
const createCompliment = function(firstName, message) {
return firstName + ': ' + message;
};
createCompliment("Molly", "You're so cool");

105/697
Parámetros predeterminados

▶ Los parámetros predeterminados se incluyen en la especificación ES6, por lo que,


en caso de que no se proporcione un valor para el argumento, se utilizará el valor
predeterminado
▶ Por ejemplo, podemos configurar cadenas predeterminadas para los parámetros
name y activity:
function logActivity(name = "Shane McConkey", activity = "skiing") {
console.log(name + ' loves ' + activity);
}
▶ Si no se proporcionan argumentos a la función logActivity, se ejecutará
correctamente utilizando los valores predeterminados

106/697
Parámetros predeterminados cont.

▶ Si no se proporcionan argumentos a la función logActivity, se ejecutará


correctamente con los valores predeterminados
▶ Los argumentos predeterminados pueden ser de cualquier tipo, no solo cadenas

const defaultPerson = {
name: {
first: "Shane",
last: "McConkey"
},
favActivity: "skiing"
};

function logActivity(person = defaultPerson) {


console.log(person.name.first + ' loves ' + person.favActivity);
}

107/697
Función flecha

▶ Las funciones flecha son una característica nueva y útil de ES6


▶ Con funciones flecha, puede crear funciones sin usar la palabra clave de function
▶ Además, a menudo no es necesario usar la palabra clave return
▶ Consideremos una función que toma name y devuelve una cadena, convirtiendo a
la persona en un lord
const lordify = function(firstName) {
return firstName + ' of Canterbury';
};
console.log(lordify("Dale")); // Dale of Canterbury
console.log(lordify("Gail")); // Gail of Canterbury
▶ Con una función flecha, podemos simplificar enormemente la sintaxis:
const lordify = firstName => firstName + ' of Canterbury';

108/697
Función flecha cont.

▶ Con la función flecha, ahora tenemos la declaración de una función completa en


una sola línea
▶ Si la función solo toma un argumento, podemos eliminar los paréntesis alrededor
de los argumentos
▶ Para más de un argumento se deben usar los paréntesis:
// Función clásica
const lordify = function(firstName, land) {
return firstName ' + of + ' land;
};

// Función flecha
const lordify = (firstName, land) => firstName + ' of ' + land;

console.log(lordify("Don", "Piscataway")); // Don of Piscataway


console.log(lordify("Todd", "Schenectady")); // Todd of Schenectady

109/697
Función flecha cont.

▶ Si el cuerpo de la función está compuesta por varias sentencias, debemos utilizar


llaves:
const lordify = (firstName, land) => {
if (!firstName) {
throw new Error("A firstName is required to lordify");
}

if (!land) {
throw new Error("A lord must have a land");
}

return firstName + ' of ' + land;


};

console.log(lordify("Kelly", "Sonoma")); // Kelly of Sonoma


console.log(lordify("Dave")); // ! JAVASCRIPT ERROR

110/697
Devolviendo objetos
▶ ¿Qué sucede si queremos devolver un objeto? Consideremos una función llamada
person que construye un objeto basado en parámetros firstName y lastName:

const person = (firstName, lastName) =>


{
first: firstName,
last: lastName
}

console.log(person("Brad", "Janson"));
▶ Tan pronto como ejecute esto, verá el error:
Uncaught SyntaxError: Unexpected token :
▶ Para solucionar esto, simplemente envuelva el objeto que está devolviendo entre
paréntesis:
const person = (firstName, lastName) => ({
first: firstName,
last: lastName
});

console.log(person("Flad", "Hanson")); 111/697


Javascript

Gestión de la memoria

112/697
Introducción

▶ La mayoría de las veces, probablemente podamos desarrollar aplicaciones


JavaScript sin saber nada sobre la administración de memoria
▶ Después de todo, el motor de JavaScript se encarga de la gestión de memoria por
nosotros
▶ Sin embargo, en algún momento pueden aparecer problemas, como fugas de
memoria, que solo puede resolver si sabe cómo funciona la asignación de memoria

113/697
Ciclo de vida de la memoria
▶ En JavaScript, cuando creamos variables, funciones o cualquier cosa, el motor JS
asigna memoria para esto y la libera una vez que ya no se necesita
▶ La asignación de memoria es el proceso de reservar espacio en la memoria,
mientras que la liberación de memoria libera espacio dejandola disponible para
otro propósito
▶ Cada vez que asignamos una variable o creamos una función, la memoria utilizada
para ese propósito pasa por las siguientes etapas:
▶ Asignar memoria: JavaScript se encarga de esto por nosotros: asigna la memoria
que necesitaremos para el objeto que creamos
▶ Usar memoria: Usar la memoria es algo que hacemos explícitamente en nuestro
código: leer y escribir en la memoria no es más que leer o escribir desde o hacia una
variable
▶ Liberar memoria: Este paso también es manejado por el motor de JavaScript. Una
vez que se libera la memoria asignada, se puede usar para un nuevo propósito
▶ ”Objetos” en el contexto de la gestión de memoria no solo incluye objetos JS sino
también funciones
114/697
El Heap y el Stack de memoria

▶ ¿Dónde se almacena toda esa memoria que se asigna?


▶ Los motores de JavaScript tienen dos lugares donde pueden almacenar datos:
▶ El Heap de memoria
▶ El Stack de memoria
▶ El Heap y el Stack son dos estructuras de datos que el motor utiliza para
diferentes propósitos

115/697
Stack: asignación de memoria estática

▶ Una pila es una estructura de datos que utiliza JavaScript para almacenar datos
estáticos
▶ Los datos estáticos son datos en los que el motor conoce el tamaño
▶ En JavaScript, esto incluye valores primitivos (cadenas, números, booleanos,
undefined y null) y referencias que apuntan a objetos y funciones

116/697
Stack: asignación de memoria estática cont.

▶ Dado que el motor sabe que el tamaño no cambiará, asignará una cantidad fija de
memoria para cada valor
▶ El proceso de asignación de memoria justo antes de la ejecución se conoce como
asignación de memoria estática
▶ Debido a que el motor asigna una cantidad fija de memoria para estos valores,
existe un límite de cuán grandes pueden ser los valores primitivos
▶ Los límites de estos valores y el tamaño del Stack varían según el navegador

117/697
Heap: asignación de memoria dinámica

▶ El Heap es un espacio diferente para almacenar datos donde JavaScript almacena


objetos y funciones
▶ A diferencia del Stack, el motor no asigna una cantidad fija de memoria para estos
objetos. En cambio, se asignará más espacio según sea necesario
▶ La asignación de memoria de esta manera también se denomina asignación de
memoria dinámica

118/697
Stack vs Heap

▶ Para obtener una descripción general, estas son las características de los dos tipos
de almacenamiento en una aplicación JavaScript:
▶ Pila
▶ Valores primitivos y referencias
▶ El tamaño se conoce en tiempo de compilación
▶ Asigna una cantidad fija de memoria
▶ Heap
▶ Objetos y funciones
▶ El tamaño se conoce en tiempo de ejecución
▶ Sin límite por objeto

119/697
Ejemplos

▶ JavaScript asigna memoria para el siguiente objeto en el Heap


const person = {
name: 'John',
age: 24,
};
▶ Los arreglos también son objetos, por lo que se almacenan en el Heap
const hobbies = ['hiking', 'reading'];
▶ Los valores primitivos son inmutables, lo que significa que en lugar de cambiar el
valor original, JavaScript crea uno nuevo.
let name = 'John'; // reserva memoria para la cadena
const age = 24; // reserva memoria para el número

name = 'John Doe'; // reserva memoria para una nueva cadena


const firstName = name.slice(0,4); // reserva memoria para una nueva cadena

120/697
Referencias en JavaScript

▶ Todas las variables se almacenan en el Stack


▶ En caso de que sea un valor no primitivo, el Stack contiene una referencia al
objeto en el Heap
▶ La memoria del Heap no está ordenada de ninguna manera en particular, por lo
que debemos mantener una referencia a ella desde el Stack

121/697
Referencias en JavaScript cont.

122/697
Recolección de basura

▶ Una vez que el motor de JavaScript reconoce que una determinada variable o
función ya no es necesaria, libera la memoria que ocupaba
▶ El encargado de realizar esta tarea es el recolector de basura
▶ Existen distintos algoritmos para la recoleccion de basura:
▶ La recolección de basura de conteo de referencias
▶ El algoritmo de marca y barrido

123/697
Javascript

Paso por Valor y por referencia

124/697
Introducción

▶ Dependiendo del tipo de dato que pasamos como argumento a una función,
podemos diferenciar dos comportamientos:
▶ Paso por valor: Se crea una copia local de la variable dentro de la función
▶ Paso por referencia: Se maneja directamente la variable, los cambios realizados
dentro de la función le afectarán también fuera
▶ Tradicionalmente:
▶ Los tipos simples se pasan por valor: enteros, flotantes, cadenas, booleanos…
▶ Los tipos compuestos se pasan por referencia: Listas, diccionarios, conjuntos…

125/697
Paso por valor de valores primitivos

▶ En el paso por valor, la función se llama pasando directamente el valor de la


variable como argumento
▶ La función que recibe el argumento, crea una copia local de dicho valor
▶ Por lo tanto, cambiar el valor del argumento dentro de la función no afecta el
valor de la variable que se paso desde fuera de la función
▶ Es importante tener en cuenta que en JavaScript, todos los argumentos de
función siempre se pasan por valor
▶ Es decir, JavaScript copia los valores de las variables de paso en argumentos
dentro de la función

126/697
Paso por valor de valores primitivos cont.

▶ Veamos el siguiente ejemplo


function square(x) {
x = x * x;
return x;
}

let y = 10;
let result = square(y);

console.log(result);
console.log(y);

127/697
Paso por valor de valores primitivos cont.
▶ En primer lugar definimos una función square() que acepta un argumento x
▶ La función asigna el cuadrado de x al argumento x
▶ A continuación, declaramos la variable y e inicializamos su valor en 10
Stack

y = 10

128/697
Paso por valor de valores primitivos cont.
▶ Luego, pasamos la variable y a la función square()
▶ Al pasar la variable y a la función square(), JavaScript copia el valor y a la
variable x
Stack

x = 10

y = 10

129/697
Paso por valor de valores primitivos cont.
▶ Luego de esto, la función square() cambia el valor de la variable x
▶ Sin embargo, el cambio no afecta el valor de la variable y porque x e y son
variables independientes
Stack

x = 100

y = 10

130/697
Paso por valor de valores primitivos cont.

▶ Finalmente, el valor de la variable y no cambia después de que se completa la


ejecución de la función square()
Stack

result = 100

y = 10

131/697
Paso por referencia

▶ Si JavaScript usara el paso por referencia, la variable y cambiaría a 100 después


de la llamada a la función
▶ En el paso por referencia, se invoca a una función pasando directamente la
referencia/dirección de la variable como argumento
▶ Cambiar el argumento dentro de la función afecta a la variable que se paso desde
fuera de la función
▶ En JavaScript, los objetos y las matrices se pasan por referencia

132/697
Pasaje por referencia cont.

function callByReference(varObj) {
console.log('Inside Call by Reference Method');
varObj.a = 100;
console.log(varObj);
}

let varObj = {
a: 1
};

console.log('Before Call by Reference Method');


console.log(varObj);

callByReference(varObj);

console.log('After Call by Reference Method');


console.log(varObj);

133/697
Paso por valor de los valores de referencia

▶ No es tan obvio ver que los valores de referencia en realidad se pasan también por
valor
▶ Por ejemplo:
let person = {
name: 'John',
age: 25,
};

function increaseAge(obj) {
obj.age += 1;
}

increaseAge(person);

console.log(person)

134/697
Paso por valor de los valores de referencia cont.

▶ Primero, definimos la variable person que hace referencia a un objeto con dos
propiedades name y age:
Stack Heap

{ name: "John",...

person

135/697
Paso por valor de los valores de referencia cont.
▶ A continuación, definimos la función increaseAge() que acepta un objeto obj y
aumenta la propiedad age del argumento obj en uno
▶ Luego, pasamos el objeto person a la función increaseAge():

Stack Heap

obj { name: "John",...

person

136/697
Paso por valor de los valores de referencia cont.
▶ Internamente, el motor JavaScript crea una referencia obj y hace que esta
variable haga referencia al mismo objeto al que hace referencia la variable person
▶ Después de eso, se incrementa la propiedad de age en uno dentro de la función de
increaseAge() a través de la variable obj
Stack Heap

obj { name: "John",...

person

137/697
Paso por valor de los valores de referencia cont.

▶ Finalmente, accediendo al objeto a través de la referencia person:


Stack Heap

{ name: "John",...

person

138/697
Paso por valor de los valores de referencia cont.

▶ Al parecer JavaScript pasa un objeto por referencia dado que el cambio en el


objeto se refleja fuera de la función. Sin embargo, éste no es el caso
▶ De hecho, cuando pasa un objeto a una función, está pasando la referencia de ese
objeto, no el objeto real
▶ Por lo tanto, la función puede modificar las propiedades del objeto a través de su
referencia
▶ Sin embargo, hay que tener en cuenta que no es posible cambiar la referencia
original que se paso a la función dentre de la propia función

139/697
Paso por valor de los valores de referencia cont.

▶ Por ejemplo:
let person = {
name: 'John',
age: 25,
};

function increaseAge(obj) {
obj.age += 1;

// reference another object


obj = { name: 'Jane', age: 22 };
}

increaseAge(person);

console.log(person);

140/697
Paso por valor de los valores de referencia cont.

▶ En este ejemplo, la función de increaseAge() cambia la propiedad age a través


del argumento obj:
Stack Heap

obj { name: "John",...

person

141/697
Paso por valor de los valores de referencia cont.

▶ Pero, dentro de la función modifica la referencia de obj hacia otro objeto:

Stack Heap

{ name: "Jane",...

obj { name: "John",...

person

142/697
Paso por valor de los valores de referencia cont.

▶ Sin embargo, la referencia de la persona aún refiere al objeto original cuya


propiedad age cambió a 26
▶ En otras palabras, la función de increaseAge() no cambia la referencia de
person

143/697
Javascript

Motor de JavaScript

144/697
Funciones como unidad fundamental
▶ En JavaScript, podemos crear y modificar una función, usarla como argumento,
devolverla desde otra función y asignarla a una variable
▶ Todas estas habilidades nos permiten usar funciones en todas partes y de esa
forma agrupar código lógicamente

145/697
Funciones como unidad fundamental cont.

▶ Como vimos anteriormente, si necesitamos decirle al motor de JavaScript que


ejecute funciones lo hacemos de la siguiente manera:
// Definimos la función
function f1() {
// Hacemos algo
// Hacemos algo nuevamente
// Nuevamente
// Y asi sucesivamente...
}

// Invocamos la función
f1();
▶ De forma predeterminada, cada línea de una función se ejecuta secuencialmente,
una línea a la vez
▶ Lo mismo es aplicable incluso cuando invocamos múltiples funciones en el código,
nuevamente línea por línea

146/697
Pila de ejecución de funciones

Entonces, ¿qué sucede cuando definimos una función y luego la invocamos?


▶ El motor de JavaScript mantiene una estructura de datos de tipo Stack llamada
pila de ejecución de funciones
▶ El propósito del Stack es rastrear la función actual en ejecución, es decir:
▶ Cuando el motor de JavaScript invoca una función, la agrega al Stack y comienza la
ejecución
▶ Si la función actualmente en ejecución llama a otra función, el motor agrega la
segunda función al Stack y comienza a ejecutarla
▶ Una vez que termina de ejecutar la segunda función, el motor la saca del Stack
▶ El control vuelve a reanudar la ejecución de la primera función desde el punto en que
la dejó la última vez
▶ Una vez terminada la ejecución de la primera función, el motor la saca del Stack
▶ Continúa de la misma manera hasta que no haya nada que poner en el Stack

147/697
Pila de ejecución de funciones cont.

La pila de ejecución de funciones también se conoce como pila de llamadas

148/697
Pila de ejecución de funciones cont.

Veamos un ejemplo de tres funciones que se ejecutan una por una:


function f1() {
// algo de código
}
function f2() {
// algo de código
}
function f3() {
// algo de código
}

// Invocamos las funciones una a la vez


f1();
f2();
f3();

149/697
Pila de ejecución de funciones cont.

Ahora veamos qué sucede con la pila de ejecución de funciones:

150/697
Pila de ejecución de funciones cont.

Ahora veamos un ejemplo más complejo. Aquí hay una función f3() que invoca otra
función f2() que a su vez invoca otra función f1().
function f1() {
// algo de código
}
function f2() {
f1();
}
function f3() {
f2();
}

f3();

151/697
Pila de ejecución de funciones cont.

Veamos qué está pasando con la pila de ejecución de funciones:

152/697
Pila de ejecución de funciones cont.

▶ En primer lugar f3() entra en el Stack, invocando o la tra función f2()


▶ Ahora f2() se ejecuta mientras f3() permanece en el Stack
▶ Luego, la función f2() invoca f1()
▶ f1() entra en el Stack junto con f2() y f3()
▶ Primero, f1() termina de ejecutarse y sale del Stack. Justo después de que
termine f2(), y finalmente f3()
▶ Por lo tanto, todo lo que sucede dentro de la pila de ejecución de funciones es
secuencial
▶ Esta es la parte síncrona de JavaScript. El subproceso principal de JavaScript se
asegura de que se ocupa de todo lo que hay en la pila antes de que comience a
buscar en cualquier otro lugar

153/697
Cómo funcionan las API y las promesas del navegador

▶ Por lo general, ejecutar instrucciones en secuencia funciona bien


▶ Pero a veces es posible que necesite obtener datos del servidor o ejecutar una
función con un retraso, o algo que no está previsto que ocurra AHORA
▶ Entonces, deseamos que el código se ejecute de forma asincrónica
▶ En estas circunstancias, es posible que no queramos que el motor de JavaScript
detenga la ejecución del otro código secuencial
▶ El motor de JavaScript necesita administrar las cosas de manera más eficiente en
este caso

154/697
Cómo funcionan las API y las promesas del navegador cont.

Podemos clasificar la mayoría de las operaciones de JavaScript como asincrónicas con


dos disparadores principales:
▶ Eventos o funciones de la API del navegador o API web: Estos incluyen métodos
como setTimeout o controladores de eventos como hacer click, pasar el mouse
por encima, desplazarse y muchos más
▶ Promesas: Un objeto JavaScript que nos permite realizar operaciones asíncronas

155/697
Cómo manejar las API del navegador o API web

▶ Las API del navegador como setTimeout y los controladores de eventos se basan
en funciones callback
▶ Una función callback se ejecuta cuando se completa una operación asincrónica
▶ Aquí hay un ejemplo de cómo funciona una función setTimeout:
function printMe() {
console.log('print me');
}

setTimeout(printMe, 2000);
▶ La función setTimeout ejecuta la función después de que haya transcurrido una
cierta cantidad de tiempo
▶ En el código anterior, el texto print me se muestra por consola después de un
retraso de 2 segundos

156/697
Cómo manejar las API del navegador o API web cont.

Ahora supongamos que tenemos algunas líneas más de código justo después de la
función setTimeout como esta:
function printMe() {
console.log('print me');
}

function test() {
console.log('test');
}

setTimeout(printMe, 2000);
test();

¿Cuál será la salida en este caso?

157/697
Cola de tareas

▶ JavaScript mantiene una cola de funciones callback también llamada cola de


tareas
▶ Una estructura de datos de tipo cola es FIFO (Primero en entrar, primero en salir)
▶ Entonces, la función callback que primero ingresa a la cola tiene la oportunidad de
salir primero. Pero la pregunta es:
▶ ¿Cuándo el motor de JavaScript lo pone en la cola?
▶ ¿Cuándo el motor de JavaScript lo saca de la cola?
▶ ¿Adónde va cuando sale de la cola?

158/697
Cola de tareas cont.
La imagen muestra el Stack de llamadas regular. Hay dos secciones adicionales para
rastrear si una API del navegador (como setTimeout) se activa y pone en cola la
función callback de esa API

159/697
Cola de tareas cont.

▶ El motor de JavaScript sigue ejecutando las funciones en la pila de llamadas


▶ Dado que no coloca la función callback directamente en la pila, no existe ningún
código esperando/bloqueando la ejecución en la pila
▶ El motor crea un ciclo para buscar en la cola periódicamente para encontrar lo que
necesita extraer de allí
▶ Extrae una función callback de la cola al Stack de llamadas cuando el Stack esté
vacío
▶ Ahora, la función callback se ejecuta generalmente como cualquier otra función en
la pila
▶ El ciclo continúa y es lo que se conoce como el ciclo de eventos o event loop

160/697
Cola de tareas cont.

Resumiendo:
▶ Cuando se produce una llamada a la API de navegador, las funciones callback se
agregan a la cola
▶ El código continua ejecutandose en la pila
▶ El ciclo de eventos comprueba si hay una función callback en la cola
▶ Si hay alguna función en la cola y el Stack está vacío, movemos la función
callback de la cola al Stack y la ejecutamos
▶ Continúe el ciclo

161/697
Cola de tareas cont.

Veamos cómo funciona con el siguiente código:


function f1() {
console.log('f1');
}

function f2() {
console.log('f2');
}

function main() {
console.log('main');

setTimeout(f1, 0);

f2();
}

main();

162/697
Cola de tareas cont.

El código ejecuta una función setTimeout con una función callback f1(). A la
función callback le hemos dado un retraso de cero. Esto significa que esperamos que
la función f1() se ejecute inmediatamente. Luego de setTimeout ejecutamos otra
función f2()
¿Cuál será el resultado en este caso?

163/697
Cola de tareas cont.
Ahora, veamos en un flujo paso a paso para el código anterior.

164/697
Cola de tareas cont.
La secuencia de pasos sería la siguiente:
▶ La función main() entra en el Stack de llamada
▶ Tiene una llamada a la consola para imprimir la palabra main, que se ejecuta y
sale del Stack
▶ Se invoca a la API del navegador setTimeout
▶ La función callback se coloca en la cola de callbacks
▶ En el Stack, la ejecución ocurre como de costumbre, por lo que f2() entra en el
Stack. Se ejecuta la llamada a la consola de f2(). Ambos salen del Stack
▶ El main() también sale del Stack
▶ El ciclo de eventos reconoce que en el Stack está vacío y que hay una función
callback en la cola
▶ La callback f1() se mueve al Stack. Comienza su ejecución. Se ejecuta la
llamada por consola y f1() también sale del Stack
▶ En este punto, no hay nada más en el Stack y en la cola para ejecutar
165/697
Gestión de promesas

▶ Aquí hay un ejemplo de una promesa en JavaScript:


const promise = new Promise((resolve, reject) =>
resolve('I am a resolved promise');
);

166/697
Gestión de promesas cont.

▶ Después de ejecutar la promesa, podemos manejar el resultado usando el método


.then() y cualquier error con el método .catch()
promise.then(result => console.log(result));
▶ Por ejemplo, utilizamos promesas cada vez que llamamos a la función fetch()
para obtener algunos datos del backend
▶ El motor de JavaScript no usa la misma cola de callbacks que hemos visto
anteriormente para las API del navegador
▶ Utiliza otra cola especial llamada Cola de trabajos

167/697
Cola de trabajos

▶ Cada vez que se produce una promesa en el código, la función a ejecutora entra
en la cola de trabajos
▶ El ciclo de eventos examinar ambas colas, pero da prioridad a los elementos de la
cola de trabajos sobre los elementos de la cola de callbacks cuando el Stack está
libre
▶ El elemento de la cola de callbacks se denomina macro-tarea, mientras que el
elemento de la cola de trabajos se denomina micro-tarea
▶ Todo el flujo de trabajo quedaría así:
▶ Para cada ciclo del ciclo de eventos, se completa una tarea fuera de la cola de
callbacks
▶ Una vez que se completa esa tarea, el ciclo de eventos revisa la cola de trabajos.
Completa todas las micro-tareas en la cola de trabajos antes de buscar lo siguiente
▶ Si ambas colas obtuvieron entradas en el mismo momento, la cola de trabajo tiene
preferencia sobre la cola de callbacks

168/697
Cola de trabajos cont.

169/697
Cola de trabajos cont.
Veamos un ejemplo para entender mejor esta secuencia:
function f1() {
console.log('f1');
}

function f2() {
console.log('f2');
}

function main() {
console.log('main');

setTimeout(f1, 0);

new Promise((resolve, reject) =>


resolve('I am a promise')
).then(resolve => console.log(resolve))

f2();
}

main();
170/697
Cola de trabajos cont.

▶ En el código anterior, tenemos una función setTimeout() como antes, pero


hemos introducido una promesa justo después
▶ La salida debería ser la siguiente:
main
f2
I am a promise
f1

171/697
Cola de trabajos cont.

172/697
Más información

▶ https://nodejs.dev/learn/the-nodejs-event-loop

173/697
Javascript

JavaScript Asincrónico

174/697
Introducción

▶ Hay diferentes formas de manejar el código asincrónico


▶ Callbacks
▶ Promesas
▶ Async/Await

175/697
Callbacks

▶ En JavaScript, las funciones son objetos, por lo tanto podemos pasar objetos a
funciones como parámetros
▶ También podemos pasar funciones como parámetros a otras funciones y llamarlas
dentro de las funciones
▶ Los callbacks son funciones que se pasan como argumento a otra función
▶ Tomemos un ejemplo de función callback:
function printString() {
console.log("Tom");
setTimeout(function() { console.log("Jacob"); }, 3000);
console.log("Mark")
}

printString();

176/697
Callbacks cont.

▶ Si ese fuera código sincrónico, habríamos encontrado el siguiente resultado


Tom
Jacob
Mark
▶ Pero setTimeout es una función asíncrona, entonces la salida del código anterior
será:
Tom
Mark
Jacob

177/697
Callbacks cont.

▶ Hay un método incorporado en JavaScript llamado setTimeout, que llama a una


función o evalúa una expresión después de un período de tiempo determinado (en
milisegundos).
▶ En otras palabras, la función que muestra el mensaje por consola se llama después
de que algo sucedió (después de que pasaron 3 segundos para este ejemplo), pero
no antes
▶ En este caso, el callback es la función que se pasa como argumento a setTimeout

178/697
Callback utilizando función flecha

▶ También puede escribir la misma función callback anterior como una función
flecha:
function printString(){
console.log("Tom");
setTimeout(() => { console.log("Jacob"); }, 3000);
console.log("Mark")
}

printString();

179/697
Callback utilizando función flecha cont.

▶ La salida será la misma que la anterior


▶ El problema con las callbacks es que pueden llegar a crear algo llamado ”Infierno
de callbacks”
▶ Básicamente, se comienzan a anidar funciones dentro de funciones dentro de
funciones, y comienza a ser muy difícil leer el código
▶ Una forma de solucionar dicho problema es utilizar Promises, las cuales manejan
las callbacks de forma mas prolija

180/697
Callback utilizando función flecha cont.

▶ Infierno de callbacks:
function pyramidOfDoom() {
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(2)
setTimeout(() => {
console.log(3)
}, 500)
}, 2000)
}, 1000)
}

181/697
Promesas

▶ Una promesa en JavaScript es similar a una promesa en la vida real


▶ Cuando hacemos una promesa en la vida real, es una garantía de que vamos a
hacer algo en el futuro (las promesas solo se pueden hacer para el futuro)
▶ Una promesa tiene dos resultados posibles: se cumplirá cuando llegue el momento
o no se cumplirá

182/697
Promesas cont.

▶ Esto mismo pasa en las promesas de JavaScript


▶ Cuando definimos una promesa en JavaScript, se resolverá cuando llegue el
momento, o se rechazará
▶ Una promesa se usa para manejar el resultado asíncrono de una operación
▶ JavaScript está diseñado para no esperar a que un bloque de código asíncrono se
ejecute por completo antes de que puedan ejecutarse otras partes síncronas del
código
▶ Con Promises, podemos diferir la ejecución de un bloque de código hasta que se
complete una solicitud asíncrona
▶ De esta manera, otras operaciones pueden seguir ejecutándose sin interrupción

183/697
Estados de las promesas

▶ En primer lugar, una Promesa es un objeto


▶ Hay 3 estados por los que puede pasar el objeto Promesa:
▶ Pendiente: Estado Inicial, antes de que la Promesa tenga éxito o falle
▶ Resuelto: Se completa la promesa
▶ Rechazado: Promesa fallida, lanza un error
▶ Por ejemplo, cuando solicitamos datos del servidor mediante una Promesa, estará
en modo pendiente hasta que recibamos nuestros datos
▶ Si conseguimos obtener la información del servidor, la Promesa se resolverá con
éxito. Pero si no obtenemos la información, entonces la Promesa estará en estado
rechazado

184/697
Creando una promesa

▶ Para crear una promesa usamos el constructor del objeto Promise


▶ La promesa tiene dos parámetros, uno para el éxito (resolve) y otro para el
fracaso (reject):
const myPromise = new Promise((resolve, reject) => {
// ejecutor
});
▶ Vamos a crear una promesa:
const myFirstPromise = new Promise((resolve, reject) => {
const condition = true;
if(condition) {
setTimeout(function(){
resolve("Promise is resolved!"); // fulfilled
}, 300);
} else {
reject('Promise is rejected!');
}
});

185/697
Creando una promesa cont.

▶ En la promesa anterior, si la condición es verdadera, resuelve la promesa


devolviendo ”La promesa está resuelta”
▶ De lo contrario, devuelva un error ”La promesa es rechazada”
▶ Ahora veamos como utilizarla

186/697
Usando la promesa
▶ Para usar la Promesa que creamos anteriormente, usamos el método then() para
resolverla y el método catch() para rechazarla
myFirstPromise.then((successMsg) => {
console.log(successMsg);
})
.catch((errorMsg) => {
console.log(errorMsg);
});
▶ O definiendo la promesa dentro de una función:
const demoPromise = function() {
myFirstPromise
.then((successMsg) => {
console.log("Success:" + successMsg);
})
.catch((errorMsg) => {
console.log("Error:" + errorMsg);
});
}
187/697
Usando la promesa cont.

▶ En la promesa que creamos, la condición es ”verdadera”, y llamamos a


demoPromise(), luego por consola veremos la salida:
Success: Promise is resolved!
▶ Entonces, si la promesa es rechazada, saltará al método catch() y esta vez
veremos un mensaje diferente en la consola
Error: Promise is rejected!

188/697
¿Qué es el encadenamiento?

▶ A veces necesitamos llamar a múltiples solicitudes asincrónicas


▶ Luego, después de que se resuelva (o rechace) la primera Promesa, comenzará un
nuevo proceso al que podemos adjuntarlo directamente mediante un método
llamado encadenamiento.
▶ Entonces creamos otra promesa:
const helloPromise = function() {
return new Promise(function(resolve, reject) {
const message = `Hi, How are you!`;

resolve(message);
});
}

189/697
¿Qué es el encadenamiento? cont.

▶ Encadenamos esta promesa a nuestra operación anterior ”myFirstPromise” así:


const demoPromise = function() {

myFirstPromise
.then(helloPromise)
.then((successMsg) => {
console.log("Success:" + successMsg);
})
.catch((errorMsg) => {
console.log("Error:" + errorMsg);
})
}

demoPromise();
▶ Dado que nuestra condición es verdadera, la salida a nuestra consola es:
Success: Hi, How are you!
▶ Una vez que la helloPromise se encadena con .then, el subsiguiente .then
utilizara los datos del anterior
190/697
Async/Await

▶ Await es básicamente lo que se conoce como azúcar sintáctico para Promesas


▶ Usando Async/Await hace que el código asincrónico se parezca más al código
sincrónico, que es más fácil de entender para los humanos
▶ Sintaxis de Async y Await:
async function printMyAsync() {
await printString("one");
await printString("two");
await printString("three");
}

191/697
Async/Await cont.
▶ Puede ver que usamos la palabra clave async para la función contenedora
printMyAsync
▶ Esto le permite a JavaScript saber que estamos usando la sintaxis async/await,
y es necesario si desea usar Await
▶ Esto significa que no puede usar Await a nivel global
▶ Siempre necesita una función contenedora, o podemos decir que await solo se usa
con una función asíncrona
▶ La palabra clave await se usa en una función async para garantizar que todas las
promesas retornadas en la función asíncrona estén sincronizadas
▶ Await elimina el uso de callbacks en .then() y .catch()
▶ Al usar async y await, async se antepone al devolver una promesa, await se
antepone al llamar a una promesa
▶ try y catch también se utilizan para obtener el valor de rechazo de una función
asíncrona
192/697
Async/Await cont.

▶ Tomemos un ejemplo para comprender Async y Await con nuestro demoPromise:


async function demoPromise() {
try {
let message1 = await myFirstPromise;
let message2 = await helloPromise();
console.log(message2);
} catch(error) {
console.log("Error:" + error.message);
}
}

193/697
Laboratorio práctico - JavaScript Labs

Es momento de jugar con la sintaxis y estructura de


JavaScript
▶ Arreglos
▶ Control de flujo
▶ Nuevas características de ES6
▶ Promesas
▶ Async/await

194/697
Typescript

Typescript
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

195/697
Typescript

Introducción

196/697
Introducción

▶ TypeScript no es un lenguaje nuevo


▶ Es una extención del lenguaje ES6 (ECMAScript 6)
▶ TypeScript se ’transcompila’
▶ El transpiler toma como entrada código fuente en TypeScript y genera como
salida código JavaScript. Dicho código es interpretado por todos los navegadores

197/697
Características

▶ Anotaciones de Tipos
▶ Clases
▶ Interfaces
▶ Decoradores
▶ Constructores
▶ Modificadores de acceso
▶ Importación y exportación de módulos
▶ Enums
▶ Tuplas
▶ Uniones
▶ Generics

198/697
Caracteristicas cont.

Qué agrega TypeScript:


▶ Tipos: Con los tipos, tenemos que ser mucho más explícitos sobre cómo
funcionan las cosas y podemos evitar muchos errores inesperados e innecesarios al
usar tipos. Además de eso, también podemos usar IDE, que tienen compatibilidad
integrada con TypeScript, que puede captar esos tipos y brindarnos un mejor
autocompletado y errores integrados, que se muestran incluso antes de que
compilemos el código
▶ Funciones de JavaScript de próxima generación: Podemos usar ciertas
características de JavaScript de próxima generación, que podemos escribir y usar
en nuestros archivos TypeScript y luego se compilarán en código JS con
implementaciones alternativas que incluso funcionarán en navegadores más
antiguos

199/697
Caracteristicas cont.

▶ Caracteristicas que no son de JavaScript: interfaces, generics: Estas son


características que se pueden compilar en JS, y que nos ayudan durante el
desarrollo y brindan errores más claros y a evitar errores comunes
▶ Metaprogramación - Decoradores: También nos brinda ciertas funciones de
metaprogramación, como los decoradores: un tipo especial de declaración que se
puede adjuntar a una declaración de clase, método, elemento de acceso, propiedad
o parámetro

200/697
Caracteristicas cont.

▶ TS es altamente configurable: El compilador TS es altamente configurable, puede


ajustarse muy bien a nuestros requisitos: hacerlo más estricto, más flexible o
simplemente asegurarnos de que se comporte de la manera que queremos
▶ Herramientas modernas: Con los modernos, como VSCode, también obtenemos
soporte para proyectos TypeScript como la verificación de tipo y el
autocompletado

201/697
Lenguaje TypeScript

▶ Es un lenguaje Tipado (define el tipo de la variable)


▶ Es Orientado a Objetos (clases, interfaces, constructores, modificadores de acceso,
propiedades, etc.)
▶ Errores en tiempo de compilación
▶ Importante Juego de Herramientas de desarrollo
▶ Los archivos fuente poseen la extension .ts
▶ Para transpilar un archivo fuente podemos usar el comando tsc (typescript
compiler):
tsc archivo.ts
▶ Luego podemos probar la aplicación:
node archivo.js

202/697
¿Por qué usamos TypeScript?

▶ Consideremos el siguiente ejemplo de JavaScript:


function add(num1, num2) {
return num1 + num2;
}

console.log(add('2', '3'));
▶ Si invocamos la función con números se realizará la suma de los mismos
▶ Sin embargo, es posible invocar la función pasando números como cadenas o
valores de cualquier tipo, lo que podría resultar en un comportamiento no deseado

203/697
¿Por qué usamos TypeScript? cont.

▶ En este ejemplo, JavaScript concatenará esas dos cadenas, que no es lo que


queríamos hacer: el resultado será 23 en lugar de 5 (pasamos dos cadenas,
evaluadas por el operador de suma)
▶ Esto no arrojará ningún error en tiempo de ejecución, es más bien un error lógico
el cual podría generar grandes problemas con la aplicación que estamos
desarrollando
▶ Por supuesto, tenemos varias formas o estrategias de mitigarlo
▶ Podríamos agregar verificaciones if
▶ Validar y corregir la entrada del usuario, etc.
▶ Todo esto está bien, pero también podríamos detectar errores durante el
desarrollo, lo cual es posible con TypeScript
▶ TypeScript es lenguaje que nos ayuda a escribir código mejorado

204/697
Debilidad de JavaScript: tipado débil
▶ Como vimos anteriormente, JavaScript posee un tipado débil
▶ Consideremos otro ejemplo (omitiendo .html ya que solo contiene el formulario):
const button = document.querySelector('button');
const input1 = document.getElementById('num1');
const input2 = document.getElementById('num2');

function add(num1, num2) {


return num1 + num2;
}

button.addEventListener('click', function() {
console.log(add(input1.value, input2.value));
})
▶ Al ejecutar este código con los números 10 y 5, esperaríamos obtener un resultado
de 15. En su lugar, vemos 105
205/697
Debilidad de JavaScript: tipado débil cont.

▶ ¿De dónde viene este error?. Llenamos nuestro formulario y en el evento click,
pasamos dos valores y los sumamos
▶ Hay que recordar que el tipo de retorno de nuestro input1.value es siempre
una cadena, que luego se pasa a nuestra función add, y no importa si la entrada
es de tipo number, el valor recuperado siempre es sera cadena
▶ Por lo tanto, dado que ambos valores son cadenas, no se suman, sino que siempre
se concatenan
▶ Este es un problema con JavaScript con el que TypeScript puede ayudarnos
▶ Podríamos agregar una sentencia if y verificar si esos valores son números y luego
devolver la suma o else convertirlos en un número anteponiendo un +:
return +num1 + +num2
▶ La ”solución” anterior funciona, pero requiere que escribiamos código adicional

206/697
Typescript

Instalación

207/697
Instalación

▶ Para comenzar a trabajar con TypeScript vamos a instalarlo


▶ Para ello vamos a la sección de descargas
(https://www.typescriptlang.org/download) en donde disponemos de
distintas formas de instalación
▶ Vamos a realizar la instalación a traves de npm de forma global
sudo npm install -g typescript
▶ Una vez realizada la instalación de TypeScript, estará disponible de forma global
en nuestra máquina
▶ Además se instalará el compilador de TypeScript tsc

208/697
Proyecto TypeScript
▶ Los archivos TypeScript se pueden compilar con el comando tsc <archivo>.ts
▶ Es tedioso compilar varios archivos .ts en un proyecto grande
▶ Por lo tanto, TypeScript proporciona otra opción para compilar todos o ciertos
archivos .ts del proyecto
▶ Puede proporcionar opciones de compilación que se pueden almacenar en el
archivo tsconfig.json
▶ Para iniciar un nuevo proyecto de TypeScript, ingrese al directorio raíz de su
proyecto y en una ventana de terminal ejecute tsc --init
▶ Este comando generará un archivo de tsconfig.json con un mínimo de
opciones de configuración, similar al siguiente
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInteop": true,
"forceConsistentCasingInFileNames": true
}
}

209/697
Archivo tsconfig.json

▶ El detalle de las opciones disponibles se puede consultar en:


https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
▶ Un detalle del mínimo de opciones generadas es (con su valor predeterminado
entre paréntesis):
▶ target (es5): especifica la versión de destino de ECMAScript (JavaScript) a la que se
adherirá el JavaScript generado: es3, es5, es2015, es2016, es2017, es2018, es2019 o
esnext
▶ module (commonjs): especifica el sistema de carga de módulos que se usará: none,
commonjs, amd, system, umd, es2015 o esnext
▶ strict (true): habilita todas las opciones estrictas de comprobación de tipo
▶ esModuleInterop (true): permite la generación de código de interoperabilidad para
habilitar la interoperabilidad entre los módulos CommonJS y ES a través de la
creación de objetos de espacio de nombres para todas las importaciones

210/697
Pruebas con TypeScript

▶ Para poder probar de forma simple programas en TypeScript podemos utilizar una
herramienta llamada TSUN (TypeScript Upgraded Node)
▶ La instalamos de la siguiente manera: sudo npm install -g tsun
▶ Ahora podemos ejecutarlo con: tsun
▶ Tambien hay otras opciones como ser ts-node: npm install -g ts-node
▶ O de forma on-line http://typescriptlang.org

211/697
Typescript

Usando TypeScript

212/697
Usando TypeScript

▶ Para compilar TypeScript podemos ejecutar el comando tsc <archivo.ts>


▶ Simplemente tenemos que crear un archivo nuevo con extensión .ts (que es la
extensión TypeScript)
▶ Si estamos usando una estructura junto con el archivo de configuración
tsconfig.json es suficiente con ejecutar tsc
▶ Vamos a probar el código del ejemplo anterior sobre ”la debilidad de JS” y
analizar la salida

213/697
Usando TypeScript cont.

▶ Incluso podemos intentar compilar inmediatamente este código, lo que nos


arrojará un error:
error TS2339: Property 'value' does not exist on type 'HTMLElement'.
▶ Eso no solo se muestra en la compilación, también nos mostrará este error en
nuestro IDE:

▶ TypeScript, nos obliga a ser más explícitos con nuestro código

214/697
Usando TypeScript cont.

▶ Hay un par de cosas a considerar. Si bien TypeScript nos obliga a verificar dos
veces el código, debemos decirle que nuestro código es correcto una vez que
hayamos terminado de verificarlo. En aras de la exhaustividad del ejemplo
anterior, proporcionaremos un montón de comentarios:
/**
* Dado que estamos tratando con HTML, y ya nos hemos asegurado de
* que nuestros elementos existen, podemos decirle a TS que nuestro
* .value nunca será * null (porque existe) agregando un signo de
* exclamación al final del elemento asignado:
*
* const input1 = document.getElementById("num1")!;
*
* En este ejemplo, tenemos que decirle a TS qué tipo de elemento es,
* por lo que lo convertiremos al tipo HTMLInputElement. Esta es la
* sintaxis de TypeScript y podemos usarla en un archivo .ts.
*/
const button = document.querySelector("button");
const input1 = document.getElementById("num1")! as HTMLInputElement;
const input2 = document.getElementById("num2")! as HTMLInputElement;

215/697
Usando TypeScript cont.

/**
* La ventaja adicional es que podemos definir tipos.
* Al principio, TS nos dirá que no sabe de qué tipo es el argumento (num: any),
* y sería bueno agregarle un tipo para que sepamos con qué estamos tratando.
*
* Mediante el uso de la sintaxis específica, que comprende el compilador de TS,
* podemos definir el tipo de argumentos. Hacemos esto agregando dos puntos después
* de un argumento y especificando un tipo
*/
function add(num1: number, num2: number) {
return num1 + num2;
}

/**
* Nuestro IDE nos advertira por la falta de coincidencia de tipos.
* .value es de tipo cadena y estamos tratando de pasar una cadena a un argumento
* que debería ser de tipo numérico.
*
* Este error también aparecerá cuando intentemos compilar esto.
* TypeScript entiende qué tipo obtenemos de InputElement, por lo que no podemos
* pasar esto a la función add(), porque espera un número, por lo que podemos
* convertirlo rápidamente en un número anteponiendo un signo más.
*/
button.addEventListener("click", function() {
console.log(add(+input1.value, +input2.value));
})

216/697
Usando TypeScript cont.

▶ Ahora podemos compilar este código con tsc filename.ts


▶ Se compilará con éxito y obtendremos un archivo .js a cambio
▶ Vemos que obtuvimos casi el mismo código que antes, pero en Vanilla JS
▶ Cuando compilamos el código, esas funciones solo se usan para evaluar nuestro
código para encontrar posibles errores y luego se eliminan
▶ Es cierto, también tuvimos que escribir código adicional, pero nos vimos obligados
a hacerlo de una manera más limpia, lo que da como resultado un código mejor y
menos propenso a errores

217/697
Typescript

Tipos

218/697
Tipos

▶ El agregado mas importante de TypsScript sobre ES6 es el sistema de tipos


▶ Lo mejor sobre la verificación de tipos es:
▶ Ayuda al escribir código; dado que previene errores en tiempo de compilación
▶ Ayuda al leer el código; dado que clarifica las intenciones
▶ Hay que aclarar que es opcional el usar tipos en TypeScript
▶ Los tipos básicos de TypeScript son los mismos que usabamos en JavaScript:
strings, numbers, booleans, etc.

219/697
Definición de variable

▶ En TypeScript podemos utilizar la palabra reservada var para definir una variable
(como lo haciamos con JavaScript)
▶ Pero ahora podemos definirle el tipo:
var fullName: string;

220/697
Funciones

▶ Cuando declaramos funciones también podemos usar tipos en los argumentos y en


los valores de retorno:
function greetText(name: string): string {
return 'Hello ' + name;
}
▶ Los ’:’ indican que vamos a especificar el tipo de retorno de la función, que en
este caso es string
▶ Intente retornar un entero dentro de la función, ¿que sucede?

221/697
Funciones

▶ En Typescript, el compilador espera que una función reciba el número exacto y el


tipo de argumentos definidos en la firma de la función
▶ Si la función espera tres parámetros, el compilador comprueba que el usuario haya
pasado valores para los tres parámetros, es decir, comprueba si hay coincidencias
exactas
function greet(greeting: string, name: string): string {
return greeting + ' ' + name + '!';
}

greet('Hello', 'Steve');
greet('Hi');
greet('Hi', 'Bill', 'Gates');

222/697
Parámetros opcionales en funciones
▶ Todos los parámetros opcionales deben seguir a los parámetros requeridos y deben
estar al final
functino greet(greeting: string, name?: string): string {
return greeting + ' ' + name + '!';
}

greet('Hello', 'Steve');
greet('Hi');
greet('Hi', 'Bill', 'Gates');
▶ En el ejemplo anterior, el nombre del segundo parámetro está marcado como
opcional con un signo ?
▶ Por lo tanto, la función greet acepta uno o dos parámetros y devuelve una
cadena de saludo
▶ Si no especificamos el segundo parámetro, su valor será undefined
223/697
Sobrecarga de funciones
▶ Typescript proporciona el concepto de sobrecarga de funciones
▶ Puedemos tener múltiples funciones con el mismo nombre pero diferentes tipos de
parámetros y tipos de retorno
▶ Sin embargo, el número de parámetros debe ser el mismo
function add(a: string, b: string): string;

function add(a: number, b: number): number;

function add(a: any, b: any): any {


return a + b;
}

add('Hello ', 'Steve');


add(10, 20);
▶ No se admite la sobrecarga de funciones con diferentes números de parámetros
224/697
Tipos incorporados

▶ Una cadena almacena texto y se declara usando el tipo string


var fullName: string = 'James Bond';
▶ En TypeScript todos los números son representados como punto flotante. El tipo
es number var age: number = 36;
▶ El tipo boolean almacena ya sea true o false como valor
var married: boolean = true;
▶ Los arreglos se declaran de tipo Array
▶ Dado que los arreglos son colecciones de elementos, debemos especificar el tipo
para los objetos del array
▶ Podemos especificar el tipo de los items de un arreglo ya sea con Array<tipo> o
tipo[]
var jobs: Array<string> = [ 'IBM', 'Microsoft', 'Google' ];
var jobs: string[] = ['Apple', 'Dell', 'HP' ];

225/697
Tipo any
▶ Typescript tiene verificación de tipo y verificación en tiempo de compilación
▶ Sin embargo, no siempre tenemos conocimiento previo sobre el tipo de algunas
variables, especialmente cuando hay valores ingresados por el usuario de
bibliotecas de terceros
▶ En tales casos, necesitamos un tipo que pueda tratar con contenido dinámico
▶ any es el tipo por defecto si omitimos el tipo para una variable dada
▶ Una variable de tipo any permite recibir cualquier tipo de valor:
var something: any = 'as string';
something = 1;
something = [ 1, 2, 3 ];

let arr: any[] = [ 'John', 212, true ];


arr.push('Smith');
console.log(arr);
226/697
Tipo void

▶ Similar a lenguajes como Java, void se usa donde no hay ningún tipo de datos
▶ Por ejemplo, en tipo de retorno de funciones que no devuelven ningún valor
function sayHi(): void {
console.log('Hi!');
}

let speech: void = sayHi();


console.log(speech);
▶ No tiene sentido asignar void a una variable, ya que solo null o undefined se
puede asignar a void

227/697
Tipo never

▶ TypeScript introduce un nuevo tipo never, que indica los valores que nunca
ocurrirán
▶ El tipo never se usa cuando se está seguro de que algo nunca va a ocurrir
▶ Por ejemplo, se escribe una función que no volverá a su punto final o que siempre
genera una excepción
function throwError(errorMsg: string): never {
throw new Error(errorMsg);
}

function keepProcessing(): never {


while (true) {
console.log('I always does something and never ends.');
}
}
228/697
Tupla

▶ TypeScript introduce un nuevo tipo de dato llamado tupla


▶ Permite expresar un arreglo donde el tipo de elementos es fijo y conocido, pero no
necesariamente el mismo
// Declaramos el tipo tupla
let x: [ string, number ];
// lo inicializamos
x = [ 'Hola', 10 ];
// una inicialización incorrecta
x = [ 10, 'Hola' ]; // Error

let user: [ number, string, boolean, number, string ];


user = [ 1, 'Steve', true, 20, 'Admin' ];

229/697
Tupla cont.

▶ Es posible declarar un arreglo de tuplas:


let employees: [ number, string ][];
employee = [ [ 1, 'Steve' ], [ 2, 'Bill'], [ 3, 'Jeff' ]];
▶ y agregar elemento a la tupla:
var employee: [ number, string ] = [ 1, 'Steve' ];
employee.push(2, 'Bill');
console.log(employee);

230/697
Enums

▶ Existen tres tipos de enumeraciones:


▶ Numéricas
▶ Cadenas
▶ Heterogeneas

231/697
Enums numéricas
▶ Las enumeraciones funcionan nombrando valores numéricos:
enum Role { Employee, Manager, Admin };
var role: Role = Role.Employee;
▶ El valor por defecto de inicio para una enum es 0
▶ Es posible cambiar el valor de la siguiente manera:
enum Role { Employee = 3, Manager, Admin };
var role: Role = Role.Employee;
▶ El valor de los demas elementos se incrementa a partir de ahí
▶ También es posible asignar valores independientes:
enum Role { Employee = 3, Manager = 5, Admin = 7 };
var role: Role = Role.Employee;
▶ Además, podemos buscar el nombre de una enumeración dada por su valor
enum Role { Employee, Manager, Admin };
console.log('Roles:', Role[0], ',', Role[1], 'and', Role[2]);
232/697
Enums numéricas cont.
▶ El valor de un miembro de enumeración puede ser constante o calculado
▶ La siguiente enumeración incluye miembros con valores calculados:
enum PrintMedia {
Newspaper = 1,
Newsletter = getPrintedMediaCode('newsletter'),
Magazine = Newsletter * 3,
Book = 10
}

function getPrintedMediaCode(mediaName: string): number {


if (mediaName === 'newsletter') {
return 5;
}
return 0;
}
233/697
Enums de cadenas

▶ Las enumeraciones de cadenas son similares a las enumeraciones numéricas,


excepto que sus valores son cadenas
enum PrintMedia {
Newspaper = 'NEWSPAPER',
Newsletter = 'NEWSLETTER',
Magazine = 'MAGAZINE',
Book = 'BOOK'
}

console.log(PrintMedia.Newspaper);
console.log(PrintMedia['Magazine']);
▶ La diferencia entre enumeraciones numéricas y de cadena es que los valores de
enumeración numéricos se incrementan automáticamente, mientras que los valores
de enumeración de cadena deben inicializarse individualmente
234/697
Enums de cadenas

▶ Las enumeraciones heterogéneas son enumeraciones que contienen cadenas y


valores numéricos
enum Status {
Active = 'ACTIVE',
Deactivate = 1,
Pending
}

235/697
Unión

▶ Typescript nos permite usar más de un tipo de datos para una variable o un
parámetro de función
▶ Esto se llama tipo de unión:
let code: (string | number);
code = 123;
code = 'ABC';
code = false;

let empId: string | number;


empId = 111;
empId = 'E111';
empId = true;

236/697
Unión cont.

function displayType(code: (string | number)) {


if (typeof(code) === 'number')
console.log('Code is number.');
else
console.log('Code is string.');
}

displayType(123);
displayType('ABC');
displayType(true);

237/697
Inferencia de tipos

▶ No es obligatorio anotar el tipo


▶ TypeScript infiere tipos de variables cuando no hay información explícita
disponible en forma de anotaciones de tipo
▶ Los tipos son inferidos por el compilador de TypeScript cuando:
▶ Las variables se inicializan
▶ Los valores predeterminados se establecen para los parámetros.
▶ Se determinan los tipos de devolución de función
▶ Por ejemplo:
var a = 'some text';
var b = 123;
a = b;
▶ El código anterior muestra un error porque al inferir tipos, TypeScript infirió el
tipo de variable a como cadena y la variable b como número

238/697
Aserción de tipos

▶ Hay dos formas de hacer una aserción de tipo en TypeScript:


▶ Usando la sintaxis <>:
let code: any = 123;
let employeeCode = <number> code;
▶ Usando la palabra clave as:
let code: any = 123;
let employeeCode = code as number;
▶ Permite establecer el tipo de un valor y decirle al compilador que no lo infiera
▶ Tal situación puede ocurrir cuando podría estar transfiriendo código de JavaScript
y podría conocer un tipo de variable más preciso que el que está asignado
actualmente
▶ Es similar a la conversión de tipos en otros lenguajes como Java. Sin embargo, a
diferencia de Java, no existe un efecto de tiempo de ejecución de la aserción de
tipo en Typescript
239/697
Typescript

Generics

240/697
Usando generics

▶ Al escribir programas, uno de los aspectos más importantes es construir


componentes reutilizables
▶ Esto asegura que el programa sea flexible y escalable a largo plazo
▶ Los genéricos ofrecen una forma de crear componentes reutilizables
▶ Además proporcionan una manera de hacer que los componentes funcionen con
cualquier tipo de datos y no se restrinjan a un tipo de datos particular
▶ Por lo tanto, los componentes se pueden llamar o usar con una variedad de tipos
de datos
▶ Los genéricos en TypeScript son similares a los genéricos de Java

241/697
Usando generics cont.

▶ Veamos por qué necesitamos genéricos usando el siguiente ejemplo.


function getArray(items: any []): any[] {
return new Array().concat(items);
}
let myNumArr = getArray([100, 200, 300]);
let myStrArr = getArray(['Hello', 'World']);
myNumArr.push(400);
myStrArr.push('Hello TypeScript');
myNumArr.push('Hi');
myStrArr.push(500);
console.log(myNumArr);
console.log(myStrArr);

242/697
Usando generics cont.

▶ En el último ejemplo, la función getarray() acepta una arreglo de tipo any


▶ Crea un nuevo arreglo de tipo any donde le concatena elementos y lo devuelve
▶ Como usamos type any para nuestros argumentos, podemos pasar cualquier tipo
de arreglo a la función
▶ Sin embargo, esto puede no ser el comportamiento deseado. Es posible que
deseemos agregar números al arreglo de números o cadenas al arreglo de cadenas,
pero no números al arreglo de cadenas o viceversa
▶ Para resolver esto, TypeScript introdujo generics
▶ Generics utiliza la variable de tipo <T>, un tipo especial de variable que denota
tipos
▶ La variable de tipo recuerda el tipo que proporciona el usuario y trabaja solo con
ese tipo en particular
▶ A esto se le llama preservar la información de tipo
243/697
Usando generics cont.

▶ La función anterior se puede reescribir como una función genérica como se


muestra a continuación:
function getArray<T>(items: T[]): T[] {
return new Array<T>().concat(items);
}
let myNumArr = getArray<number>([100, 200, 300]);
let myStrArr = getArray<string>(['Hello', 'World']);
myNumArr.push(400);
myStrArr.push('Hello TypeScript');
myNumArr.push('Hi');
myStrArr.push(500);

244/697
Variables de tipo multiple

▶ Podemos especificar múltiples variables de tipo con diferentes nombres como se


muestra a continuación:
function displayType<T, U>(id: T, name: U): void {
console.log(typeof(id) + ', ' + typeof(name));
}

displayType<number, string>(1, 'Steve');


▶ El tipo genérico también se puede utilizar con otros tipos no genéricos:
function displayType<T>(id: T, name: string): void {
console.log(typeof(id) + ', ' + typeof(name));
}

displayType<number>(1, 'Steve');

245/697
Métodos y propiedades de tipo generics
▶ Cuando usamos variables de tipo para crear componentes genéricos, TypeScript
nos obliga a usar solo métodos generales que están disponibles para cada tipo
function displayType<T, U>(id: T, name: U): void {
id.toString();
name.toString();

id.toFixed();
name.toUpperCase();

console.log(typeof(id) + ', ' + typeof(name));


}
▶ En el ejemplo anterior, las llamadas a los métodos id.toString() y
name.toString() son correctas porque el método toString() está disponible
para todos los tipos
▶ Sin embargo, no se pueden llamar métodos específicos de tipo como toFixed()
para el tipo number o toUpperCase() para el tipo string
▶ El compilador dará un error
246/697
Laboratorio práctico - TypeScript Labs

Es momento de jugar con la sintaxis y estructura de


TypeScript
▶ Tipos básicos
▶ Funciones
▶ Enums
▶ Unions
▶ Generics

247/697
Programación Orientada a Objetos

Programación Orientada
a Objetos
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

248/697
Programación Orientada a Objetos

Introducción

249/697
Conceptos basicos de POO
▶ La programación orientada a objetos (POO) es un paradigma de programación
que se basa en el concepto de clases y objetos
▶ Se utiliza para estructurar un programa de software en piezas fundamentales
llamadas clases, que se utilizan para crear instancias individuales
▶ La programación orientada a objetos es adecuada para programas de gran
tamaño, complejos y que se actualizan o mantienen activamente
▶ Object representa uno de los tipos de datos de JavaScript
▶ Se utiliza para almacenar colecciones con clave/valor o entidades más complejas
▶ Los objetos se pueden crear de dos formas:
▶ Utilizando el constructor Object():
var myObj = new Object();
myObj.key = value;
▶ Utilizando la sintaxis declarativa (literal):
var myObj = {
key: value
// ...
};
250/697
Beneficios de la Programación Orientada a Objetos

▶ Algunos de los beneficios de la Programación Orientada a Objetos son los


siguientes:
▶ Desarrollo en terminos del dominio del problema
▶ Bajo acoplamiento a través del encapsulamiento
▶ Alta cohesión
▶ Reutilización de código a través de la herencia
▶ Flexibilidad a través del polimorfismo

251/697
Principios de la Programación Orientada a Objetos

▶ Abstracción: Proceso de clasificación de las propiedades que intervienen en la


solución
▶ Encapsulamiento: Permite dividir un programa en componentes más pequeños e
independientes. Cada componente es autónomo e independiente de los demás
componentes
▶ Herencia: Reutilizar código entre clases
▶ Polimorfismo: Los objetos pueden tomar diferentes comportamientos
dependiendo del contexto

252/697
Clases

▶ Una clase es una plantilla para la creación de objetos según un modelo


predefinido
▶ Las clases se utilizan para representar entidades o conceptos
▶ Están compuestas por miembros:
▶ Propiedades
▶ Métodos

253/697
Objetos

▶ Instancia de una clase


▶ Entidad provista de un conjunto de propiedades o atributos (datos) y de
comportamiento o funcionalidad (métodos), los mismos que consecuentemente
reaccionan a eventos
▶ Se corresponden con los objetos reales del mundo que nos rodea, o con objetos
internos del sistema (del programa)

254/697
Abstracción

▶ La abstracción es el procedimiento mediante el cual el programador captura las


características y comportamientos esenciales de un elemento
▶ Esta abstracción nos permite crear una pieza de software que emula al objeto del
mundo real

255/697
Encapsulamiento

▶ Se denomina encapsulamiento a la reunión de atributos pertenecientes a una


misma clase, al mismo nivel de abstracción, suele confundirse con el principio de
ocultación, básicamente porque este último depende del encapsulamiento
▶ El principio de ocultación consiste en garantizar que los elementos privados de una
clase no puedan ser accedidos por otra. Es decir, proteger información específica
de cualquier otro tipo de objeto diferente a la instancia actual, incluso si son de la
misma clase.
▶ Las tres características de un encapsulamiento eficaz son:
▶ Abstracción
▶ Ocultamiento de la implementación
▶ División de la responsabilidad

256/697
Herencia

▶ La herencia es un mecanismo de los lenguajes de programación orientados a


objetos, por medio del cual una clase deriva de otra (se define en base a otra) de
manera que extiende su funcionalidad
▶ La definición de la nueva clase obtiene automáticamente todos los atributos,
comportaminetos e implementaciones que contenga la clase existente
▶ La clase de la que se hereda se suele denominar clase base, clase
padre, superclase, clase ancestro

257/697
Polimorfismo

▶ Se basa en la herencia
▶ En terminos de programación permite que un solo nombre de clase o de método
represente un código diferente seleccionado mediante algún mecanismo
automático
▶ Un nombre puede tomar diferentes formas y puesto que puede representar código
diferente, también puede representar muchos comportamientos distintos
▶ Pensemos en el termino abrir. Podriamos abrir una puerta, una caja, una ventana
o una cuenta en el banco. Se puede aplicar a muchos objetos distintos en la
realidad. Cada objeto lo interpretara a su manera (se abrira de distintas formas)

258/697
Programación Orientada a Objetos

Clases

259/697
POO basado en prototipos

▶ Conceptualmente, en la programación orientada a objetos basada en clases,


primero creamos una clase que sirva como un ”modelo” para los objetos y luego
creamos objetos basados este modelo
▶ Para construir tipos de objetos más específicos, creamos clases ”secundarias”; es
decir, hacemos algunos cambios en el plano y usamos el nuevo plano resultante
para construir los objetos más específicos
▶ Para una analogía del mundo real, si tuviera que construir una silla, primero
crearíamos un plano en papel y luego fabricaría sillas basadas en este plano
▶ El modelo aquí es la clase y las sillas son los objetos
▶ Si quisiera construir una mecedora, tomaría el plano, haría algunas modificaciones
y fabricaría mecedoras utilizando el nuevo plano

260/697
POO basado en prototipos cont.

Ahora llevemos este ejemplo al mundo de los prototipos:


▶ No creamos los planos o clases aquí, solamente creamos el objeto
▶ Tomamos un poco de madera y cortamos una silla. Esta silla, un objeto real,
puede funcionar completamente como silla y servir también como prototipo para
futuras sillas
▶ En el mundo de los prototipos, construimos una silla y simplemente creamos
”clones” de ella
▶ Si deseamos construir una mecedora, todo lo que tenemos que hacer es elegir una
silla que haya fabricado anteriormente y colocarle dos mecedoras
▶ Ahora podemos disfrutar de esa mecedora, o tal vez usarla como prototipo para
crear más mecedoras

261/697
Clases

▶ En JavaScript ES5 la programación orientada a objetos se realizaba utilizando


objetos basados en prototypes en lugar de utilizar clases
▶ Sin embargo, en ES6 se incorporo el soporte para clases en JavaScript
▶ Para definir una clase usamos la nueva palabra reservada class y le damos a
nuestra clase un nombre y un cuerpo:
class Vehicle {
// cuerpo
}
▶ Las clases pueden tener propiedades, métodos y constructores

262/697
Propiedades

▶ Las propiedades definen los datos asociados a una instancia de la clase


▶ Cada propiedad en una clase puede tener de forma opcional un tipo
▶ Ejemplo:
class Person {
firstName: string;
lastName: string;
age: number;
}

263/697
Métodos

▶ Los métodos son funciones que se ejecutan en el contexto de un objeto


▶ Para invocar un método sobre un objeto, primero necesitamos una instancia de
ese objeto
▶ Para instanciar un objeto utilizamos la palabra reservada new
▶ Ejemplo:
class Person {
firstName: string;
lastName: string;
age: number;

greet() {
console.log('Hello', this.firstName);
}
}
264/697
Métodos cont.

▶ Dentro de un método es posible acceder al firstName de esa persona utilizando la


palabra reservada this
▶ Cuando los métodos no declaran un tipo de retorno de forma explicita y devuelven
un valor, se asume que pueden retornar cualquier valor (tipo any)
▶ void también es un valor válido para any
▶ Ejemplo:
// declaramos una variable de tipo Person
var p: Person;

// instanciamos una nueva Person


p = new Person();

// le asignamos un firstName
p.firstName = 'Juan';

// invocamos al metodo greet


p.greet();

265/697
Métodos cont.

▶ Es posible declarar e instanciar un objeto de una clase en la misma línea


var p: Person = new Person();
▶ Ahora es posible agregar un método a la clase Person que retorne un valor. Por
ejemplo:
class Person {
...
ageInYears(years: number): number {
return this.age + years;
}
}

266/697
Constructores

▶ Un constructor es un método especial que se ejecuta cuando se crea una nueva


instancia de la clase
▶ Generalmente, el constructor es donde se realiza cualquier tipo de inicialización de
las propiedades del nuevo objeto
▶ Los constructores se deben llamar constructor
▶ Pueden de forma opcional recibir parametros
▶ No pueden devolver ningún valor (no tienen tipo de retorno)

267/697
Constructores cont.

▶ Cuando una clase no posee un constructor explicitamente definido, se creara uno


de forma automática
class Vehicle {
}
var v = new Vehicle();
▶ Es lo mismo que:
class Vehicle {
constructor() { }
}
var v = new Vehicle();

268/697
Constructores cont.

▶ Un constructor con parámetros sería de la forma:


class Person {
firstName: string;
lastName: string;
age: number;

constructor(firstName: string, lastName: string, age: number) {


this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

greet() {
console.log('Hello', this.firstName);
}

// ... otros métodos


}

269/697
Constructores cont.

▶ Con lo cual, la creacion de la instancia inicializada se reduce a:


var p: Person = new Person('Juan', 'Maz', 36);
p.greet();

270/697
Programación Orientada a Objetos

Abstracción

271/697
Abstracción

▶ Los objetos solo revelan mecanismos internos que son relevantes para el uso de
otros objetos, ocultando cualquier código de implementación innecesario
▶ Esta funcionalidad es muy poderosa en el desarrollo y TypeScript nos proporciona
varias formas de manipular la visibilidad de los miembros de un objeto de clase
▶ Al ejemplo anterior, hemos agregado el modificador public en todos los atributos
de Person
▶ De forma predeterminada, todos los atributos son siempre public
// Clase Person
class Person {
public name: string = '';
public age: string = '';

public greetings() {
return this.name + ' ' + this.age;
}
}

272/697
Modificadores de acceso
▶ Podemos utilizar los siguientes modificadores de acceso para controlar la
visibilidad de los atributos
▶ public
▶ protected
▶ private
▶ Además, podemos usar readonly, lo que evitará las asignaciones al campo fuera
del constructor
class Person {
public readonly credentials: string = '';
public name: string = '';
public department: string = '';

constructor(value: string) {
this.credentials = value;
}

public setName(name: string): void {


if (!this.credentials) return;
this.name = name;
}
273/697
Modificadores de acceso cont.

▶ En el ejemplo anterior, si intentamos crear una nueva instancia de Person sin


proporcionar credentials, recibiremos una advertencia y no compilará
▶ Lo primero que debemos notar es que la visibilidad de las credenciales es
readonly, lo que significa que solo se puede actualizar el valor dentro del
constructor
// warining An argument for 'value' was not provided.
const person1 = new Person();

// En este caso funcionará


const person1 = new Person('123456');

274/697
Programación Orientada a Objetos

Encapsulamiento

275/697
Encapsulamiento

▶ La implementación y el estado de cada objeto se mantienen de forma privada


dentro de un límite definido o clase
▶ Otros objetos no tienen acceso a esta clase o la autoridad para realizar cambios,
pero solo pueden llamar a una lista de funciones o métodos públicos
▶ Esta característica de ocultación de datos proporciona una mayor seguridad del
programa y evita la corrupción de datos no deseada

276/697
Encapsulamineto cont.

▶ Por lo tanto, una buena práctica es definir a los atributos como private y que no
se puedea acceder a ellos desde fuera de la clase
▶ Tenga en cuenta que solo podemos acceder a campos públicos fuera de la
definición de la clase
▶ Si cambiamos el nivel de acceso de los campos de la clase Person a private:
// Creamos el objeto Preson person1
const person1 = new Person('123456');

person1. // esto enumerará automáticamente todas las propiedades accesibles


// Note que no se puede acceder a los atributos privados fuera de la definición de la clase

277/697
Encapsulamineto cont.

▶ En el siguente ejemplo, hemos definido dos clases de objetos y hemos creado una
instancia de cada uno
▶ El principio de encapsulación establece que la nueva instancia de motor1 no
puede acceder a los atributos de person1
▶ Si intentaramos acceder, obtendriamos una advertencia de este tipo
La propiedad 'edad' no existe en el tipo 'Motor'

278/697
Encapsulamiento cont.

// Clase persona
class Person {
name: string = '';
age: number = 0;
}

// Clase motor
class Motor {
make: string = '';
model: string = '';
color: string = '';
}

// Creamos una instancia de cada una


const person1 = new Person();
const motor1 = new Motor();

// Advertencia: Property 'age' does not exist on type 'Motor'.


motor1.age();

279/697
Propiedades getters y setters

▶ Hay dos tipos de propiedades de objeto


▶ Propiedades de los datos: Ya sabemos cómo trabajar con ellas. Todas las
propiedades que hemos estado usando hasta ahora eran propiedades de datos
▶ Propiedad accesor o mutador: Son esencialmente funciones que se ejecutan al
obtener o establecer un valor, pero parecen propiedades normales para un código
externo

280/697
Propiedades getters y setters cont.

▶ Las propiedades de acceso están representadas por los métodos getter y setter
▶ En un objeto literal, se denotan por get y set:
let obj = {
get propName() {
// getter, el código ejecutado al obtener obj.propName
},

set propName(value) {
// setter, el código ejecutado al configurar obj.propName = value
}
};

281/697
Propiedades getters y setters cont.

▶ Supongamos tener un objeto que represente a una persona con su nombre y


apellido
▶ Ahora queremos agregar una propiedad fullName que devuelva la concatenación
de nombre y apellido
▶ Podríamos implementarla con un get/set:
let user = {
name: "John",
surname: "Smith",

get fullName() {
return `${this.name} ${this.surname}`;
}
};

console.log(user.fullName); // John Smith

282/697
Programación Orientada a Objetos

Herencia

283/697
Herencia

▶ La herencia es una forma de indicar que una clase ”recibe” o hereda el


comportamiento de otra clase llamada clase base o clase padre
▶ Por lo tanto, pueden modificarse, sustituirse o aumentarse aquellos
comportamientos (métodos) en la nueva clase
▶ TypeScript soporta completamente la herencia y se implementa utilizando la
palabra reservada extends
▶ Se pueden asignar relaciones de subclases entre objetos, lo que permite a los
desarrolladores reutilizar una lógica común manteniendo una jerarquía única

284/697
Herencia cont.
▶ Creemos una nueva clase encargada de generar reportes:
class Report {
data: Array<string>;

constructor(data: Array<string>) {
this.data = data;
}

run() {
this.data.forEach((line) => console.log(line));
}
}
▶ Ahora podemos probar la clase Report de la siguiente manera:
var r: Report = new Report([ 'First line', 'Second line' ]);
r.run();
285/697
Herencia cont.
▶ Si queremos aplicar herencia sobre la clase Report hacemos un extends sobre la
misma:
class TabbedReport extends Report {
headers: Array<string>;

constructor(headers: string[], values: string[]) {


super(values);
this.headers = headers;
}

run() {
console.log(this.headers);
super.run();
}
}
286/697
Herencia cont.

▶ Ahora podemos probar el nuevo reporte TabbedReport que hereda del anterior:

var headers: string[] = [ 'Name' ];


var data: string[] =
[ 'Alice Green', 'Paul Pfifer', 'Louis Blakenship' ];
var r: TabbedReport = new TabbedReport(headers, data);
r.run();

287/697
Programación Orientada a Objetos

Polimorfismo

288/697
Polimorfismo

▶ Los objetos pueden tomar más de una forma dependiendo del contexto
▶ El programa determinará qué significado o uso es necesario para cada ejecución de
ese objeto, reduciendo la necesidad de duplicar código
▶ El polimorfismo se basa en la sustitución

289/697
Ejemplo

Analicemos el siguente ejemplo y veamos como podemos mejorarlo:


class Person {
public name: string = '';
public role: string = '';
}

class BasketballPlayer extends Person {


public setName(name: string) {
this.name = name
this.role = 'BasketBall Player';
}
public getName() {
return `User name: ${this.name} Role: ${this.role}`;
}
}

290/697
Polimorfismo cont.

class GolfPlayer extends Person {


public setName(name: string) {
this.name = name;
this.role = 'Golf Player';
}
public getName() {
return `User name: ${this.name} Role: ${this.role}`;
}
}

const person1 = new BasketballPlayer();


const person2 = new GolfPlayer();
person1.setName('Kevin Odongo');
person2.setName('Kevin Odongo');
console.log(person1.getName());
console.log(person2.getName());

291/697
Estructuras de datos

Estructuras de datos
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

292/697
Estructuras de datos

Estructuras de datos

293/697
¿Que son las estructuras de datos?

▶ A un alto nivel, son técnicas para almacenar y organizar datos que facilitan su
modificación, navegación y acceso
▶ Determinan cómo se agrupan los datos, las funciones que podemos usar para
acceder a ellos y las relaciones entre los datos
▶ Se utilizan en casi todas las áreas de la informática y la programación

294/697
¿Que son las estructuras de datos? cont.

▶ Diferentes tareas requieren diferentes estructuras de datos


▶ Lista de datos indexados, con duplicados
▶ Lista de datos sin un orden particular, donde no se permiten duplicados
▶ Pares clave/valor de datos sin ordenar
▶ Pares clave/valor de datos ordenados y iterables
▶ Las estructuras de datos nos permiten:
▶ Administrar y utilizar grandes conjuntos de datos
▶ Simplificar y acelerar el procesamiento de datos

295/697
¿Que son las estructuras de datos? cont.

▶ JavaScript tiene estructuras de datos primitivas y no primitivas


▶ Estructuras de datos primitivas: Las estructuras de datos primitivas son nativas del
lenguaje de programación. En JavaScript se incluyen arreglos, Set, Object, Map
▶ Estructuras de datos no primitivas: Las estructuras de datos no primitivas no están
definidas por el lenguaje de programación. Es responsabilidad del programador
crearlas. Estas incluyen estructuras de datos como colas y listas enlazadas, etc.

296/697
Estructuras de datos

Arreglos

297/697
Arreglos
▶ La más básica de todas las estructuras de datos, es el arreglo que almacena datos
en la memoria para su uso posterior
▶ Cada arreglo tiene un número de celdas accesibles a través de un índice numérico
correspondiente
▶ El orden donde se inserta el elemento se mantiene
▶ Son iterables (for..of)
▶ Son dinamicos
▶ Permite tener elementos duplicados
▶ Borrar o buscar elementos puede llegar a ser costoso en terminos de procesamiento

298/697
Arreglos cont.

▶ Ventajas
▶ Sencillos de crear y utilizar
▶ Bloque de construcción fundamental para estructuras de datos más complejas
▶ Desventajas
▶ Costoso para insertar/eliminar (resecuenciar valores)
▶ Ineficiente para ordenar
▶ Aplicaciones
▶ La mayoria de los algoritmos utilizan arreglos
▶ Las propias estructuras de datos no primitivas

299/697
Estructuras de datos

Set

300/697
Set

▶ El orden de inseción no se almacena


▶ Por lo tanto no se pueden acceder a través de un índice
▶ Son iterables (for..of)
▶ Su tamaño se ajusta de forma dinámica
▶ No permite elementos duplicados
▶ La busqueda de elementos o el borrado es mucho más eficiente que en los arreglos

301/697
Arreglos vs Set

▶ Arreglos
▶ El orden en el cual se almacenan los elementos es importante
▶ Se necesitan almacenar duplicados
▶ Set
▶ El orden en el cual se almacenan no es importante
▶ No se permiten duplicados
▶ Simplifica la busqueda o el borrado de elementos

302/697
Estructuras de datos

Objects

303/697
Object

▶ Datos en forma de clave/valor sin un orden particular


▶ Los elementos se acceden a traves de la clave (nombre de la propiedad)
▶ No son iterables (se puede acceder a las propiedades con for..in)
▶ Las claves son únicas, los valores no
▶ Las claves deben ser strings, numbers o symbols
▶ Pueden almacenar datos y funcionalidad (methods)

304/697
Estructuras de datos

Maps

305/697
Map

▶ Los pares clave/valor estan ordenados


▶ Los elementos se acceden a través de la clave
▶ Es iterable (for..of)
▶ Las claves son únicas, los valores no
▶ Las calves pudeden ser cualquier tipo (includas las referencias)
▶ Almacenadores de datos puros, optimizados para el acceso

306/697
Objetos vs Maps

▶ Objects
▶ Es muy versatil
▶ Se deben utilizar si es necesario agregar funcionalidad adicional
▶ Maps
▶ Se centra en el almacenamiento y acceso a datos
▶ Mejor performance que los Objetos
▶ El tipo Object de JavaScript es un tipo especial de implementación de Map por
dos razones:
▶ Tiene propiedades añadidas por la clase Object. Las llaves que introduzcas pueden
entrar en conflicto y sobrescribir las propiedades por defecto heredadas de la clase
▶ El tamaño del Map no es contabilizado. Es necesario contar manualmente cuántas
propiedades son definidas por el programador en lugar de ser heredadas del prototipo

307/697
Estructuras de datos

WeakSet y WeakMap

308/697
WeakSet y WeakMap

▶ Son variaciones de Set y de Map


▶ Los valores y los claves son ”weakly referenced”
▶ El Garbage collector puede borrar valores y claves si detecta que no se estan
utilizando dentro de la app

309/697
Estructuras de datos

Lista enlazada

310/697
Lista enlazada
▶ Es una lista de elementos que no utiliza la ubicación física de los datos en la
memoria
▶ En lugar de índices o posiciones, las listas enlazadas utilizan un sistema de
referencia: los elementos se almacenan en nodos que contienen una referencia al
siguiente nodo
▶ Este sistema permite la inserción y extracción eficiente de elementos sin necesidad
de reorganización

311/697
Lista enlazada cont.

▶ Ventajas
▶ Inserción y extracción eficiente de elementos
▶ Menos complejo que reestructurar un arreglo
▶ Desventajas
▶ Utiliza más memoria que los arreglos
▶ Ineficaz para recuperar un elemento específico
▶ Ineficaz para recorrer la lista hacia atrás
▶ Aplicaciones
▶ Conviene utilizarlo cuando se deben agregar o eliminar datos sucesivos desde
ubicaciones aleatorias

312/697
Lista enlazada cont.

Veamos una implementación de la lista enlazada:


▶ Vamos a definir la clase Node que represente un nodo de la lista
class Node {
constructor(data, next = null) {
this.data = data;
this.next = next;
}
}
▶ También vamos a definir una clase LinkedList que represente a nuestra lista
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
}

313/697
Lista enlazada cont.

▶ La LinkedList tiene un encabezado, que primero se establece en null (se podria


agregar un argumento al constructor para establecer el valor)
▶ También almacenamos el tamaño de la lista enlazada
▶ El primer lugar vamos a ver la implementación del método insert
▶ Este método agregará un nuevo nodo al final de nuestra lista enlazada

314/697
Lista enlazada cont.
// insertar agregará al final de nuestra lista enlazada
insert(data) {
// creamos un objeto nodo utilizando los datos recibidos
let node = new Node(data);
let current;
// si no tenemos un inicio de la lista, creamos uno
if (!this.head) {
this.head = node;
} else {
// si ya existe un inicio de lista, agregamos el nodo a la lista
current = this.head;
// vamos hasta el final de la lista enlazada (el nodo sin valor en next)
while (current.next) {
current = current.next;
}
// establecemos el valor de next para que sea el nodo actual
current.next = node;
}
// incrementamos el tamaño
this.size++;
}

315/697
Lista enlazada cont.

▶ El siguiente método que vamos a implementar es remove


▶ Este método eliminará un nodo con un valor particular

316/697
Lista enlazada cont.
remove(value) {
// comenzamos en el inicio de la lista
let current = this.head;
// mantenemos una referencia al nodo anterior
if (!current) {
return;
}
let previous;
while (current && current.data !== value) {
previous = current;
current = current.next;
}
if (!current) {
return;
}
if (!previous) {
this.head = current.next;
} else {
previous.next = current.next;
}
this.size--;
}
317/697
Lista enlazada cont.

▶ El método anterior va actualizando next para que apunte al siguiente nodo de la


lista hasta que alcancemos el nodo con el valor buscado
▶ El método más simple que queda por implementar es clearList
clearList() {
this.head = null;
this.size = 0;
}
▶ Esto restablece el estado de la lista al momento de la creación
▶ Hay muchos métodos que puede agregar a lista enlazada. Lo anterior establece los
fundamentos básicos

318/697
Estructuras de datos

Árboles

319/697
Definición

▶ Un árbol es una estructura no lineal en la que cada nodo puede apuntar a uno o
varios nodos

320/697
Conceptos

▶ En relación con otros nodos:


▶ Nodo hijo: cualquiera de los nodos apuntados por uno de los nodos del árbol. En el
ejemplo, ’L’ y ’M’ son hijos de ’G’.
▶ Nodo padre: nodo que contiene un puntero al nodo actual. En el ejemplo, el nodo
’A’ es padre de ’B’, ’C’ y ’D’.
▶ Los árboles con los que trabajaremos tienen otra característica importante: cada
nodo sólo puede ser apuntado por otro nodo, es decir, cada nodo sólo tendrá un
padre. Esto hace que estos árboles estén fuertemente jerarquizados, y es lo que en
realidad les da la apariencia de árboles.

321/697
Posición

▶ En cuanto a la posición dentro del árbol:


▶ Nodo raíz: nodo que no tiene padre. Este es el nodo que usaremos para referirnos
al árbol. En el ejemplo, ese nodo es el ’A’.
▶ Nodo hoja: nodo que no tiene hijos. En el ejemplo hay varios: ’F’, ’H’, ’I’, ’K’, ’L’,
’M’, ’N’ y ’O’.
▶ Nodo rama: Estos son los nodos que no pertenecen a ninguna de las dos categorías
anteriores. En el ejemplo: ’B’, ’C’, ’D’, ’E’, ’G’ y ’J’.

322/697
Características

▶ Todos los nodos contienen el mismo número de punteros, es decir, usaremos la


misma estructura para todos los nodos del árbol. Esto hace que la estructura sea
más sencilla, y por lo tanto también los programas para trabajar con ellos.
▶ Tampoco es necesario que todos los nodos hijos de un nodo concreto existan. Es
decir, que pueden usarse todos, algunos o ninguno de los punteros de cada nodo.
▶ Un árbol en el que en cada nodo o bien todos o ninguno de los hijos existe, se
llama árbol completo.
▶ Dado un nodo cualquiera de la estructura, podemos considerarlo como una
estructura independiente. Es decir, un nodo cualquiera puede ser considerado
como la raíz de un árbol completo.

323/697
Características en relación a su tamaño

▶ Orden: es el número potencial de hijos que puede tener cada elemento de árbol.
De este modo, diremos que un árbol en el que cada nodo puede apuntar a otros
dos es de orden dos, si puede apuntar a tres será de orden tres, etc.
▶ Grado: el número de hijos que tiene el elemento con más hijos dentro del árbol.
En el árbol del ejemplo, el grado es tres, ya que tanto ’A’ como ’D’ tienen tres
hijos, y no existen elementos con más de tres hijos.
▶ Nivel: se define para cada elemento del árbol como la distancia a la raíz, medida
en nodos. El nivel de la raíz es cero y el de sus hijos uno. Así sucesivamente. En el
ejemplo, el nodo ’D’ tiene nivel 1, el nodo ’G’ tiene nivel 2, y el nodo ’N’, nivel 3.
▶ Altura: la altura de un árbol se define como el nivel del nodo de mayor nivel.
Como cada nodo de un árbol puede considerarse a su vez como la raíz de un
árbol, también podemos hablar de altura de ramas. El árbol del ejemplo tiene
altura 3, la rama ’B’ tiene altura 2, la rama ’G’ tiene altura 1, la ’H’ cero, etc.

324/697
Árboles ordenados

▶ Un árbol ordenado, es aquel a partir del cual se puede obtener una secuencia
ordenada siguiendo uno de los recorridos posibles del árbol
▶ En estos árboles es importante que la secuencia se mantenga ordenada aunque se
añadan o se eliminen nodos.
▶ Existen varios tipos de árboles ordenados. Dos de ellos son:
▶ árboles binarios de búsqueda (ABB): son árboles de orden 2 que mantienen una
secuencia ordenada si se recorren en orden.
▶ árboles AVL: son árboles binarios de búsqueda equilibrados, es decir, los niveles de
cada rama para cualquier nodo no difieren en más de 1.

325/697
Definición de Recorridos

▶ inorden: recorrer en inorden el subárbol izquierdo, visitar el elemento de la raíz y


luego recorrer en inorden el subárbol derecho
▶ preorden: visitar el elemento de la raíz , recorrer en preorden el subárbol
izquierdo y luego recorrer en preorden el subárbol derecho.
▶ postorden: recorrer en postorden el subárbol izquierdo, luego recorrer en
postorden el subárbol derecho y finalmente visitar el elemento de la raíz.

326/697
Definición de Recorridos cont.
▶ Ejemplo de recorridos:
inorden : 10 , 30 , 50 , 55 , 60 , 80
preorden : 60 , 30 , 10 , 50 , 55 , 80
postorden : 10 , 55 , 50 , 30 , 80 , 60

327/697
Estructuras de datos

Tablas hash

328/697
Tablas hash
▶ Las tablas hash (Map) son una estructura de datos compleja capaz de almacenar
grandes cantidades de información y recuperar elementos específicos de manera
eficiente
▶ Esta estructura de datos se basa en el concepto de pares clave/valor, donde la
”clave” es una cadena buscada y el ”valor” son los datos emparejados con esa
clave

329/697
Tablas hash cont.

▶ Cada clave se convierte de su forma de cadena en un valor numérico, llamado


hash, utilizando una función hash predefinida
▶ Este hash luego apunta a un lugar de almacenamiento, un subgrupo más pequeño
dentro de la tabla
▶ Luego busca en el depósito la clave ingresada originalmente y devuelve el valor
asociado con esa clave

330/697
Tablas hash cont.

▶ Ventajas
▶ La clave puede tener cualquier forma, mientras que los índices de la matriz deben ser
números enteros
▶ Función de búsqueda altamente eficiente
▶ Número constante de operaciones para cada búsqueda
▶ Costo constante por operaciones de inserción o eliminación
▶ Desventajas
▶ Colisiones: un error causado cuando dos claves se convierten en el mismo código
hash o dos códigos hash apuntan al mismo valor
▶ Estos errores pueden ser comunes y, a menudo, requieren una revisión de la función
hash
▶ Aplicaciones
▶ Almacenamiento de base de datos
▶ Búsquedas de direcciones por nombre

331/697
Estructuras de datos

Complejidad de los algoritmos

332/697
Complejidad del algoritmo

▶ Cada algoritmo requiere una cantidad diferente de tiempo y recursos


▶ Nos referiremos a estas restricciones como complejidad de tiempo y complejidad
de recursos
▶ Estas dos características son cruciales para que podamos decidir qué algoritmo se
adapta mejor a nuestras necesidades
▶ Cuando hablamos de algoritmos, normalmente usamos métricas como la
complejidad del tiempo (cuánto tiempo requiere el algoritmo para resolver un
problema) y la complejidad del espacio (cuánta memoria requiere el algoritmo
para resolver un problema).
▶ La manera más formal de expresar estos valores es a traves de la notacion big O

333/697
Notacion Big O

▶ Es una métrica relativa que muestra qué tan rápido crecerá el tiempo de ejecución
del algoritmo o su memoria consumida dependiendo del crecimiento del tamaño
de entrada
▶ Los valores absolutos de tiempo y memoria varían en diferentes hardware, por lo
que debemos usar una métrica relativa
▶ El mismo programa puede ejecutarse en 1 segundo en una computadora y en 10
segundos en otra
▶ Cuando comparamos las complejidades de tiempo de dos algoritmos, se requiere
que se ejecuten en la misma configuración de hardware predefinida, lo que no es
conveniente y, a veces, no es reproducible
▶ La notación Big O define la relación entre tamaño de entrada frente tiempo
dedicado para la complejidad del tiempo y tamaño de entrada frente a la
memoria consumida para la complejidad del espacio

334/697
Notacion Big O cont.

▶ Constante: O(1)
▶ Logarítmico: O(log n)
▶ Lineal: O(n)
▶ Linearítmica: O(n log(n))
▶ Cuadrático: O(n2 )
▶ Exponencial: O(2n )
▶ Factorial: O(n!)

335/697
Notacion Big O cont.
▶ Gráficos de funciones comúnmente utilizados en el análisis de algoritmos

336/697
Notacion Big O cont.

La siguente tabla lista de algunas de las notaciones Big O más comunes y sus
comparaciones de rendimiento con diferentes tamaños de datos de entrada

Big O Notation 10 elementos 100 elementos 1000 elementos


O(1) 1 1 1
O(log(n)) 3 6 9
O(n) 10 100 1000
O(n log(n)) 30 600 9000
O(n2 ) 100 10000 1000000
O(2n ) 1024 1.26e+29 1.07e+301
O(n!) 3628800 9.3e+157 4.02e+2567

337/697
Ejemplo de O(1)

▶ Eleva un número a la potencia


/**
* Raise number to the power.
*
* Example:
* number = 3
* power = 2
* output = 3^2 = 9
*
* @param {number} number
* @param {number} power
* @return {number}
*/
function fastPower(number, power) {
return number ** power;
}

338/697
Ejemplo O(n)
▶ Eleva un número a la potencia
/**
* Raise number to the power.
*
* Example:
* number = 3
* power = 2
* output = 3^2 = 9
*
* @param {number} number
* @param {number} power
* @return {number}
*/
function iterativePower(number, power) {
let result = 1;

for (let i = 0; i < power; i += 1) {


result *= number;
}

return result;
}
339/697
Ejemplo recursivo de O(n)

▶ Calcular factoriales
/**
* Calculate factorial.
*
* Example:
* number = 5
* output = 120
*
* @param {number} number
* @return {number}
*/
function factorial(number) {
if (number === 0) {
return 1;
}
return factorial(number - 1) * number;
}

340/697
Ejemplo de O(n²)

▶ Obtenga todos los pares posibles de las letras proporcionadas


/**
* Get all possible pairs out of provided letters.
*
* Example:
* letter = ['a', 'b']
* output = ['aa', 'ab', 'ba', 'bb']
*
* @param {string[]} letters
* @return {string[]}
*/
function pairs(letters) {
const result = [];
for (let i = 0; i < letters.length; i += 1) {
for (let j = 0; j < letters.length; j += 1) {
result.push(`${letters[i]}${letters[j]}`);
}
}
return result;
}

341/697
Laboratorio práctico - Estructura de datos Labs
Es momento de practicar con las estructuras de
datos
▶ Ejercicios con estructuras de datos primitivas
arreglos, Set y Map
▶ Implementación de una lista enlazada
▶ Implementación de una lista doblemente
enlazada
▶ Implementación de una Pila
▶ Implementación de una Cola
▶ Implementación de una Cola circular
▶ Implementación de un Árbol binario
▶ Implementación propia de un Map sin utilizar la
clase de ES6
342/697
Algoritmos

Algoritmos
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

343/697
Algoritmos

Sorting

344/697
Estrategias aplicadas durante el ordenamiento

▶ Recursión: La recursión es un método de programación en el que se define una


función en términos de sí misma. La función generalmente se llama a sí misma
con parámetros ligeramente modificados (para converger)
▶ Divide y vencerás: el algoritmo cumple su tarea dividiendo el problema en
subproblemas más pequeños y resolviéndolos para llegar a la solución general

345/697
Ordenamiento

▶ Algoritmos de ordenamientos:
▶ Bubble Sort
▶ Selection Sort
▶ Insertion Sort
▶ Merge Sort
▶ Quick Sort

346/697
Métodos auxiliares para intercambiar y comparar

▶ Vamos a definir un método auxiliar llamado swap para el intercambio de


elementos:
function swap(arr, a, b) {
let temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
▶ También creamos una función para comparar elementos:
const Compare = {
LESS_THAN: -1,
BIGGER_THAN: 1
};

function defaultCompare(a, b) {
if (a === b) {
return 0;
}
return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
}

347/697
Bubble Sort

▶ El ordenamiento de burbujas es uno de los algoritmos de clasificación más simples


▶ En su mayoría es bueno para fines de enseñanza, ya que es uno de los algoritmos
de ordenamiento más lentos
▶ Compara cada dos valores adyacentes y los intercambia si el primero es más
grande que el segundo
▶ Esto refleja su nombre ya que los valores tienden a subir en el orden correcto,
como burbujas que suben a la superficie
▶ Pseudo código
▶ Comenzamos comparando los dos primeros elementos de un arreglo
▶ Los cambiamos si es necesario
▶ Continuamos hasta el final del arreglo
▶ En este punto, hemos encontrado el mayor de los valor
▶ Repetimos el proceso hasta ordenar todo el arreglo

348/697
Bubble Sort cont.

349/697
Bubble Sort cont.

function bubbleSort(arr, compare = defaultCompare) {


const { length } = arr;
for (let i = 0; i < length; i++) {
for (let j = 0; j < length - 1 - i; j++) {
if (compare(arr[j], arr[j + 1]) === Compare.BIGGER_THAN) {
swap(arr, j, j + 1);
}
}
}
return arr;
}

350/697
Insertion sort
▶ Hay una parte del arreglo que está ordenado y otro sin ordenar
▶ Debemos comparar los elementos de la parte no ordenada uno por uno e
insertarlos en la parte ordenada en el orden correcto
▶ Pseudo código en orden ascendente
▶ Comenzamos comparando el segundo elemento del arreglo con el primer elemento,
suponiendo que el primer elemento es la parte ordenadai
▶ Intercambiamos si el segundo elemento es más pequeño que el primero
▶ Iteramos comparando el primer elemento con cada elemento de la parte no ordenada
▶ Si el elemento de la parte no ordenada es más pequeño que el primer elemento lo
intercambiamos
▶ Luego de recorrer todo el arreglo, incrementamos la parte ordenada al siguiente
índice y comparamos recursivamente el valor del último índice de la parte ordenada
con cada valor de la parte no ordenada
▶ Intercambiamos donde el valor de la porción sin clasificar es menor
▶ La porción ordenada crecerá hasta que cubra todo el arreglo dando como resultado
una matriz ordenada
351/697
Insertion Sort cont.

352/697
Insertion Sort cont.

function insertionSort(arr, compare = defaultCompare) {


const { length } = arr;
let temp;
for (let i = 1; i < length; i++) {
let j = i;
temp = arr[i];
while (j > 0 && compare(arr[j - 1], temp) === Compare.BIGGER_THAN) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
return arr;
}

353/697
Selection Sort

▶ La idea básica detrás del algoritmo de ordenamiento por selección es encontrar el


valor mínimo en la estructura de datos
▶ Una vez encontrado se lo coloca en la primera posición
▶ Luego se encuentra el segundo valor mínimo, y se lo coloca en la segunda posición
▶ Así sucesivamente hasta completar la estructura

354/697
Selection Sort cont.

355/697
Selection Sort cont.

function selectionSort(arr, compare = defaultCompare) {


const { length } = arr;
let minIndex;
for (let i = 0; i < length - 1; i++) {
minIndex = i;
for (let j = i; j < length; j++) {
if (compare(arr[minIndex], arr[j]) === Compare.BIGGER_THAN) {
minIndex = j;
}
}
if (i !== minIndex) {
swap(arr, i, minIndex);
}
}
return arr;
}

356/697
Merge Sort

▶ El algoritmo de ordenamiento por combinación es un algoritmo de tipo divide y


vencerás
▶ En otras palabras, divide el arreglo original en arreglos más pequeños hasta que
cada arreglo más pequeñio tenga solo una posición
▶ Luego combina los arreglos más pequeños en uno más grande que se ordena

357/697
Merge Sort cont.

358/697
Merge Sort cont.

function mergeSort(arr, compare = defaultCompare) {


if (arr.length > 1) {
const { length } = arr;
const middle = Math.floor(length / 2);
const left = mergeSort(arr.slice(0, middle), compare);
const right = mergeSort(arr.slice(middle, length), compare);
arr = merge(left, right, compare);
}
return arr;
}

function merge(left, right, compare) {


let i = 0;
let j = 0;
const result = [];
while (i < left.length && j < right.length) {
result.push(compare(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]);
}
return result.concat(i < left.length ? left.slice(i) : right.slice(j));
}

359/697
Quick Sort

▶ Quick sort es uno de los algoritmos de ordenamiento más utilizados


▶ Similar a la ordenación por combinación, Quick sort también utiliza el enfoque
divide y vencerás
▶ Dividamos el proceso en pasos para comprenderlo mejor, ya que es más complejo
que los anteriores:
▶ Seleccionamos un valor del arreglo que llamaremos pivote, generalmente el valor a
la mitad del arreglo
▶ Realizamos la operación de partición que dará como resultado un arreglo con valores
menores que el pivote a la izquierda y mayores a la derecha
▶ Repetimos los primeros dos pasos para cada subarreglo (izquierda y derecha) hasta
que los arreglos estén completamente ordenados

360/697
Quick Sort cont.

361/697
Quick Sort cont.

function partition(items, left, right) {


var pivot = items[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}

362/697
Quick Sort cont.

function quickSort(items, left, right) {


var index;
if (items.length > 1) {
index = partition(items, left, right);
if (left < index - 1) {
quickSort(items, left, index - 1);
}
if (index < right) {
quickSort(items, index, right);
}
}
return items;
}

363/697
Algoritmos

Algoritmos de búsqueda

364/697
Algoritmos de búsqueda

▶ Se utilizan en la tarea relacionada con la búsqueda de elementos dentro de


nuestras estructuras
▶ La búsqueda es más fácil gracias a estos algoritmos
▶ La búsqueda es fundamental para cualquier lenguaje de programación
▶ Vamos a analizar los siguientes algoritmos de búsqueda
▶ Linear Search: cuando los elementos de datos son aleatorios o no están ordenados,
usamos la búsqueda secuencial o lineal
▶ Binary Search: cuando los elementos están ordenados, usamos la búsqueda binaria
▶ La búsqueda binaria solo funciona cuando sus datos están ordenados, y debemos
tener en cuenta el costo de ordenar los datos incluso antes de comenzar a
buscarlos

365/697
Linear Search

▶ Este es el tipo básico de búsqueda


▶ Dada una lista de datos, comenzamos desde el principio de la colección e iteramos
a través de cada elemento hasta encontrar lo que estamos buscando
▶ La complejidad del tiempo de ejecución para la búsqueda lineal es O(n)

366/697
Pseudo código

▶ La función acepta un arreglo y un valor


▶ Recorremos el arreglo y verificamos si el elemento del arreglo actual es igual al
valor que estamos buscando
▶ Si es así, devuelve el índice en el que se encuentra el elemento
▶ Si nunca se encuentra el valor, devuelve -1
var linearSearch = function(cities, value) {
for(let i = 0; i < cities.length; i++) {
if(cities[i] === value) return i;
}
return -1;
}
var cities = [ "Rosario", "Rafaela", "Santa Fe", "San Javier",
"Ceres", "Las Toscas", "Recreo", "Laguna Paiva", "Sunchales" ];
console.log(linearSearch(cities, "San Javier"));

367/697
Binary Search

▶ Si tenemos un conjunto de datos que está ordenado, entonces la búsqueda binaria


es una mejor manera de buscar
▶ La búsqueda binaria funciona como lo harían los humanos si estuvieran buscando
en un diccionario, por ejemplo:
▶ Si tuvieramos que buscar CÓDIGO en un diccionario, no iríamos a la sección ’A’ y
comenzaríamos la búsqueda allí
▶ Comenzaríamos más hacia la mitad del libro (digamos alrededor de la letra M)
▶ Según si el alfabeto en el que abrimos el diccionario es más adelante o más atrás de
lo que estamos buscando, sabemos en qué dirección continuar la búsqueda

368/697
Pseudo código

▶ La función acepta un arreglo ordenado y el valor a buscar


▶ Creamos un puntero izquierdo al comienzo del arreglo y un puntero derecho al
final del arreglo
▶ Mientras que el puntero izquierdo venga antes que el puntero derecho:
▶ Creamos un puntero en el medio
▶ Si encuentramos el valor que deseamos, devuelvemos el índice
▶ Si el valor es demasiado pequeño, muevemos el puntero izquierdo hacia arriba
▶ Si el valor es demasiado grande, muevemos el puntero derecho hacia abajo
▶ Si nunca encuentramos el valor, devuelva -1

369/697
Implementacion

var binarySearch = function(arr, elem) {


let start = 0;
let end = arr.length - 1;
let middle = Math.floor(start + end / 2);
while(arr[middle] !== elem && start <= end) {
if(elem < arr[middle]) {
end = middle - 1;
} else {
start = middle + 1;
}
middle = Math.floor((start+end)/2)
}
return arr[middle] === elem ? middle : -1;
}

console.log(binarySearch([2, 4, 6, 9, 11, 14, 20, 25, 28, 40], 11));

370/697
Patrones de diseno

Patrones de diseno
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

371/697
Patrones de diseno

Patrones diseño

372/697
Patrones diseño

Hay 23 patrones de diseño clásicos que se describen en el libro original ”Patrones de


diseño: Elementos de software orientado a objetos reutilizable”. Los patrones brindan
una solución a un problema particular que se repite en el desarrollo del software.
▶ Se pueden dividir en distintos tipos según su proposito:
▶ De creación: gestionan la creación de objetos
▶ De comportamiento: que coordinan la interacción funcional entre ellos
▶ Estructurales: que gestionan relaciones estáticas y de estructuras
▶ De sistema: que gestionan la interacción a nivel de sistema

373/697
Patrones de diseno

Singleton

374/697
Singleton

Permite tener una única instancia global a toda nuestra aplicación


▶ Singletons son clases que se pueden instanciar una vez y se puede acceder a ellas
globalmente
▶ Esta instancia única se puede compartir en toda nuestra aplicación, lo que hace
que Singletons sea excelente para administrar el estado global en una aplicación
▶ Veamos cómo sería un singleton usando una clase ES2015. Para este ejemplo,
vamos a construir la clase Counter que tenga:
▶ un método getInstance que devuelve el valor de la instancia
▶ un método getCount que devuelve el valor actual de la variable contador
▶ un método increment que incrementa el valor del contador en uno
▶ un método decrement que decrementa el valor del contador en uno

375/697
Singleton cont.
1 class Counter {
2
3 constructor() {
4 this.counter = 0;
5 }
6
7 getInstance() {
8 return this;
9 }
10
11 getCount() {
12 return this.counter;
13 }
14
15 increment() {
16 this.counter++;
17 }
18
19 decrement() {
20 this.counter--;
21 }
22 }
376/697
Singleton cont.

▶ Sin embargo, la clase asi definida no cumple con los criterios para un Singleton
▶ Un Singleton solo debería poder ser instanciado una vez, pero en el ejemplo
anterior podemos crear múltiples instancias de la clase Counter
const counter1 = new Counter();
const counter2 = new Counter();

console.log(counter1.getInstance() === counter2.getInstance()); // false

377/697
Singleton cont.

▶ Los valores retornados por el método getInstance sobre las referencias


counter1 y counter2 devuelven referencias a distintas instancias: ¡no son
estrictamente iguales! i
▶ Una forma de asegurarse de que solo se pueda crear una instancia es creando un
campo llamado instance
▶ En el constructor de Counter, podemos establecer instance igual a una
referencia de instance cuando se crea una nueva instancia
▶ Podemos evitar nuevas instancias comprobando si instance tiene un valor
asignado
▶ Si ese es el caso, ya existe una instancia y deberíamos generar un error

378/697
Singleton cont.
class Counter {
static instance;
constructor() {
this.counter = 0;
if (Counter.instance) {
throw new Error("You can only create one instance!");
}
Counter.instance = this;
}

getInstance() {
return Counter.instance;
}

getCount() {
return this.counter;
}

increment() {
this.counter++;
}

decrement() {
this.counter--;
}
}

const counter1 = new Counter();


const counter2 = new Counter();
// Error: You can only create one instance!

379/697
Pruebas

▶ Armar pruebas unitarias de un Singleton puede ser complicado


▶ No podemos crear nuevas instancias por cada prueba
▶ Todas las pruebas se basan en la modificación de la única instancia de la prueba
anterior
▶ El orden de las pruebas es importante en este caso, y una pequeña modificación
puede hacer que falle todo un conjunto de pruebas
▶ Después de cada prueba, necesitamos limpiar la instancia de las modificaciones
realizadas

380/697
Patrones de diseno

Ejemplo en JavaScript

381/697
Ejemplo utilizando objetos

1 l e t count = 0;
2
3 const c o u n t e r = {
4 increment () {
5 r e t u r n c o u n t ++;
6 },
7 decrement () {
8 r e t u r n count −−;
9 }
10 };
11
12 Object . f r e e z e ( counter ) ;
13 ex po rt { c o u n t e r } ;

382/697
Patrones de diseno

Factory

383/697
Factory

Permite definir un método estándar para crear un objeto


▶ Con el patrón Factory podemos usar funciones para ”fabricar” o crear nuevos
objetos
▶ Una función es una función de fábrica cuando devuelve un nuevo objeto sin el uso
de la palabra clave new
▶ Por ejemplo, podríamos crear nuevos usuarios con las propiedades firstName,
lastName e email
▶ La función de fábrica agregaría la propiedad fullName al objeto recién creado
const createUser = ({ firstName, lastName, email }) => ({
firstName,
lastName,
email,
fullName() {
return `${this.firstName} ${this.lastName}`;
}
});

384/697
Introducción

▶ Ahora podemos crear fácilmente varios usuarios invocando la función createUser

const user1 = createUser({


firstName: "John",
lastName: "Doe",
email: "[email protected]"
});

const user2 = createUser({


firstName: "Jane",
lastName: "Doe",
email: "[email protected]"
});

console.log(user1);
console.log(user2);

385/697
Factory cont.

▶ La función de fábrica puede ser útil si estamos creando objetos relativamente


complejos y configurables
▶ Podría suceder que los valores de las claves y los valores dependan de un
determinado entorno o configuración
▶ Con la función fábrica podemos crear fácilmente nuevos objetos que contengan
claves y valores personalizados
const createObjectFromArray = ([key, value]) => ({
[key]: value
});

createObjectFromArray(["name", "John"]); // { name: "John" }

386/697
Patrón método de fábrica

▶ El patrón de diseño Factory Method es uno de los patrones de diseño


fundamentales y forma parte de los patrones de diseño ”Gang of Four”
▶ Su objetivo es proporcionar una solución para la creación de objetos sin especificar
la clase exacta del objeto que se crea
▶ Imagine crear un sistema para la enseñanza de codificación en línea. Una de tus
clases probablemente sería un Teacher
class Teacher {
constructor(name, programmingLanguage) {
this.name = name;
this.programmingLanguage = programmingLanguage;
}
}

387/697
Patrón método de fábrica cont.

▶ Se ve bien a primera vista, pero el enfoque anterior podría no ser escalable


▶ Si decidimos expandir nuestro negocio a la enseñanza de la música también,
podríamos terminar con algo como esto:
const TEACHER_TYPE = {
CODING: 'coding',
MUSIC: 'music'
};

class Teacher {
constructor(type, name, instrument, programmingLanguage) {
this.name = name;
if (type === TEACHER_TYPE.CODING) {
this.programmingLanguage = programmingLanguage;
} else if (type === TEACHER_TYPE.MUSIC){
this.instrument = instrument;
}
}
}

388/697
Patrón método de fábrica cont.

▶ Como se puede ver, la clase Teacher se está tornando compleja y seguira


empeorando aún más a medida que agreguemos más tipos de Teacher en base de
código existente
▶ Un enfoque común para el problema anterior es implementar el patrón
Factory Method
const TEACHER_TYPE = {
CODING: 'coding',
MUSIC: 'music'
};

class CodingTeacher {
constructor(properties) {
this.name = properties.name;
this.programmingLanguage = properties.programmingLanguage;
}
}

389/697
Patrón método de fábrica cont.

class MusicTeacher {
constructor(properties) {
this.name = properties.name;
this.instrument = properties.instrument;
}
}

class TeacherFactory {
static getTeacher(type, properties) {
if (type === TEACHER_TYPE.CODING) {
return new CodingTeacher(properties);
} else if (type === TEACHER_TYPE.MUSIC) {
return new MusicTeacher(properties);
}
}
}

390/697
Patrón método de fábrica cont.

▶ En el código anterior, podemos usar TeacherFactory para crear cualquier tipo


de maestro
▶ Además, no tenemos que preocuparnos por romper ningún código al agregar un
nuevo tipo
const codingTeacher = TeacherFactory.getTeacher(TEACHER_TYPE.CODING, {
programmingLanguage: 'JavaScript',
name: 'John'
});

const musicTeacher = TeacherFactory.getTeacher(TEACHER_TYPE.MUSIC, {


instrument: 'Guitar',
name: 'Andy'
});

391/697
Patrones de diseno

Patrón Command

392/697
Patrón Command

Desacoplar métodos que ejecutan tareas mediante el envío de comandos


▶ Con el patrón de comando, podemos encapsular un comando en un objeto de
forma tal que pueda ser almacenado, pasado a métodos y retornado al igual que
cualquier otro objeto
▶ Digamos que tenemos una plataforma de entrega de alimentos en línea
▶ Los usuarios pueden realizar, rastrear y cancelar pedidos

393/697
Patron Command cont.

class OrderManager {
constructor() {
this.orders = [];
}

placeOrder(order) {
this.orders.push(order);
return `You have successfully ordered ${order.description} (${order.id})`;
}

trackOrder(order) {
return `Your order ${order.id} will arrive in 20 minutes.`;
}

cancelOrder(order) {
this.orders = this.orders.filter(elem => elem.id !== order.id);
return `You have canceled your order ${order.id}`;
}
}

394/697
Patrón command cont.

▶ En la clase OrderManager, tenemos acceso a los métodos placeOrder,


trackOrder y cancelOrder
const order = { id: 1, description: 'Mesa' };
const manager = new OrderManager();

manager.placeOrder(order);
manager.trackOrder(order);
manager.cancelOrder(order);
▶ Sin embargo, existen desventajas al invocar los métodos directamente en la
instancia de OrderManager

395/697
Patrón Command cont.

▶ Queremos desacoplar los métodos del objeto OrderManager y crear funciones que
encapsulen la funcionalidad de forma individual (comando)
▶ Vamos a refactorizar la clase OrderManager: en lugar de tener los métodos
placeOrder, cancelOrder y trackOrder, tendrá un único método: ejecutar
▶ Este método ejecutará cualquier comando que se le pase como argumento

396/697
Patrón Command cont.

▶ Cada comando debe tener acceso a las órdenes del OrderManager, que pasaremos
como su primer argumento
class OrderManager {
constructor() {
this.orders = [];
}

execute(command, ...args) {
return command.execute(this.orders, ...args);
}
}
▶ Necesitamos crear tres comandos para el administrador de pedidos:
▶ PlaceOrderCommand
▶ CancelOrderCommand
▶ TrackOrderCommand

397/697
Patrón Command cont.

class Command {
constructor(execute) {
this.execute = execute;
}
}

function PlaceOrderCommand(order) {
return new Command(orders => {
orders.push(order);
return `You have successfully ordered ${order.description} (${order.id})`;
});
}

function CancelOrderCommand(order) {
return new Command(orders => {
orders = orders.filter(elem => elem.id !== order.id);
return `You have canceled your order ${order.id}`;
});
}

function TrackOrderCommand(order) {
return new Command(() => `Your order ${order.id} will arrive in 20 minutes.`);
}

398/697
Patrón Command cont.

const order = { id: 1, description: 'Mesa' };

const manager = new OrderManager();

manager.execute(new PlaceOrderCommand(order));
manager.execute(new TrackOrderCommand(order));
manager.execute(new CancelOrderCommand(order));
▶ Ventajas
▶ El patrón de comando nos permite desacoplar los métodos del objeto que ejecuta la
operación
▶ Le da más control si se trata de comandos que tienen una vida útil determinada o
comandos que deben ponerse en cola y ejecutarse en momentos específicos

399/697
Patrones de diseno

Strategy

400/697
Strategy

▶ El patrón de estrategia encapsula algoritmos alternativos (o estrategias) para una


tarea en particular
▶ Permite cambiar un método en tiempo de ejecución por cualquier otro método
(estrategia) sin que el cliente se dé cuenta
▶ Esencialmente, la estrategia es un grupo de algoritmos que son intercambiables

401/697
Usando Strategy

▶ Digamos que nos gusta probar el rendimiento de diferentes algoritmos de


ordenamiento de una serie de números: ordenamiento de burbujas, Quick sort, etc
▶ La aplicación del patrón de estrategia a estos algoritmos permite que el programa
de prueba recorra todos los algoritmos, simplemente cambiándolos en tiempo de
ejecución y probando cada uno de ellos con un arreglo
▶ Para que la estrategia funcione, todas las firmas de los métodos deben ser las
mismas para que puedan variar sin que el programa cliente lo sepa.
▶ En JavaScript, el patrón de estrategia se usa ampliamente como un mecanismo de
addons en la creación de frameworks extensibles

402/697
Diagram

403/697
Ejemplo cont.

class StrategyManager {
constructor() {
this._strategies = [];
}

addStrategy(strategy) {
this._strategies = [...this._strategies, strategy];
}

getStrategy(name) {
return this._strategies.find(strategy => strategy._name === name);
}
}

class Strategy {
constructor(name, handler) {
this._name = name;
this._handler = handler;
}

doAction() {
this._handler;
}
}

404/697
Ejemplo cont.

const strategyManager = new StrategyManager();


const strategy1 = new Strategy('strategy1', () => console.log('Strategy1'));
const strategy2 = new Strategy('strategy2', () => console.log('Strategy2'));

strategyManager.addStrategy(strategy1);
strategyManager.addStrategy(strategy2);

const strategyA = strategyManager.getStrategy('strategy1');


strategyA.doAction();

const strategyB = strategyManager.getStrategy('strategy2');


strategyB.doAction();

const strategyC = strategyManager.getStrategy('strategy3');


try {
strategyC.doAction();
} catch (err) {
console.error('Caught Error');
console.error(err);
}

405/697
Patrones de diseno

Façade

406/697
Façade

▶ El patrón Façade proporciona una interfaz que protege a los clientes de una
funcionalidad compleja en uno o más subsistemas
▶ Es un patrón simple que puede parecer trivial pero es poderoso y extremadamente
útil
▶ A menudo está presente en los sistemas que se construyen en torno a una
arquitectura de múltiples capas

407/697
Usando Façade

▶ La intención de Façade es proporcionar una interfaz de alto nivel que haga que un
subsistema o conjunto de herramientas sea fácil de usar para el cliente
▶ En el servidor, en una aplicación Web multicapa, con frecuencia posee una capa
de presentación que es cliente para una capa de servicio
▶ La comunicación entre estas dos capas se realiza a través de una API bien definida
▶ Esta API, o Façade, oculta las complejidades de los objetos y sus interacciones de
la capa de presentación
▶ Otra área donde se utilizan Façades es en la refactorización
▶ Suponga que tiene un conjunto confuso o desordenado de objetos heredados por
los que el cliente no debería preocuparse
▶ Puedes ocultar este código detrás de una Façade. El Façade expone solo lo
necesario y presenta una interfaz más limpia y fácil de usar
▶ Las Façade se combinan frecuentemente con otros patrones de diseño
408/697
Diagrama

409/697
Ejemplo cont.

let currentAccountNumber = 0;

class AccountManager {
createAccount(type, details) {
const accountNumber = AccountManager.getUniqueAccountNumber();
let account;
if (type === 'current') {
account = new CurrentAccounts();
} else {
account = new SavingsAccounts();
}
return account.addAccount({ accountNumber, details });
}

static getUniqueAccountNumber() {
return ++currentAccountNumber;
}
}

410/697
Ejemplo cont.

class Accounts {
constructor() {
this.accounts = [];
}

addAccount(account) {
this.accounts.push(account);
return this.successMessage(account);
}

getAccount(accountNumber) {
return this.accounts.find(account => account.accountNumber === accountNumber);
}

successMessage(account) {}
}

411/697
Ejemplo cont.

class CurrentAccounts extends Accounts {


constructor() {
super();
if (CurrentAccounts.exists) {
return CurrentAccounts.instance;
}
CurrentAccounts.instance = this;
CurrentAccounts.exists = true;
return this;
}

successMessage({ accountNumber, details }) {


return `Current Account created with ${details}. ${accountNumber} is your account number.`;
}
}

412/697
Ejemplo cont.

class SavingsAccounts extends Accounts {


constructor() {
super();
if (SavingsAccounts.exists) {
return SavingsAccounts.instance;
}
SavingsAccounts.instance = this;
SavingsAccounts.exists = true;
return this;
}

successMessage({ accountNumber, details }) {


return `Savings Account created with ${details}. ${accountNumber} is your account number.`;
}
}

413/697
Ejemplo cont.

const accountManager = new AccountManager();

const currentAccount = accountManager.createAccount('current',


{ name: 'John Snow', address: 'pune' });

const savingsAccount = accountManager.createAccount('savings',


{ name: 'Petter Kim', address: 'mumbai' });

414/697
Material adicional

▶ https://medium.com/javascript-scene/javascript-factory-functions-
with-es6-4d224591a8b1

415/697
Laboratorio práctico - Patrones de diseno Labs

Es momento de practicar los patrones de diseno


▶ Singleton
▶ Factory
▶ Command
▶ Strategy
▶ Façade

416/697
Programación funcional

Programación funcional
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

417/697
Programación funcional

Funciones de orden superior

418/697
Funciones de orden superior

▶ Una función de orden superior es una función que opera sobre funciones, tomando
una o más funciones como argumentos y devolviendo una nueva función.
// This higher-order function returns a new function that passes its
// arguments to f and returns the logical negation of f's return value;
function not(f) {
return function(arg) { // Return a new function
let result = f(arg); // that calls f
return !result; // and negates its result.
};
}

const even = x => x % 2 === 0; // A function to determine if a number is even


const odd = not(even); // A new function that does the opposite
[ 1, 1, 3, 5, 5 ].every(odd); // => true: every element of the array is odd

419/697
Funciones de orden superior cont.

Para ilustrar la escritura de funciones de orden superior con flechas, veamos un ejemplo
clásico: sumar. En ES5 se vería así:
function add(x){
return function(y){
return y + x;
};
}

var addTwo = add(2);


addTwo(3); // => 5
add(10)(11); // => 21

420/697
Funciones de orden superior cont.

La función escrita como función HOF:


const add = x => y => y + x;

var addTwo = add(2);


addTwo(3); // => 5
add(10)(11); // => 21

421/697
Funciones de orden superior cont.

Como función de iteración sobre sort, forEach, filter, some


const isNumber = n => x => x === n;
const arr = [ '1', '2', '3'];

arr.filter(isNumber('3'));

▶ Esto es útil por varias razones:


▶ Reduce el código repetitivo
▶ Permite una reutilización más fácil del código
▶ Aumenta la claridad del significado del código

422/697
Programación funcional

Funciones puras

423/697
Definición

▶ Una función pura es una función que siempre devuelve el mismo resultado si se
pasan los mismos argumentos
▶ No depende de ningún cambio de estado o datos durante la ejecución de un
programa
▶ Solo depende de sus argumentos de entrada
▶ Además, una función pura no produce ningún efecto secundario observable, como
solicitudes de red o mutación de datos, etc.
function calculateGST( productPrice ) {
return productPrice * 0.05;
}

424/697
Definición cont.

▶ Veamos ahora otro ejemplo:


var tax = 20;
function calculateGST( productPrice ) {
return productPrice * (tax / 100) + productPrice;
}
▶ Nota: Si una función pura llama a una función pura, esto no es un efecto
secundario y la función que llama todavía se considera pura
▶ ¿Algún ejemplo?

425/697
Definición cont.

A continuación se presentan algunos efectos secundarios (pero no limitados a) que una


función no debería producir para ser considerada como una función pura:
▶ Hacer una solicitud HTTP
▶ Mutar datos
▶ Impresión en una pantalla o consola
▶ Consulta/Manipulación DOM
▶ Math.random()
▶ Obtener la hora actual

426/697
Programación funcional

Definición

427/697
Nuevas funciones de arreglos

▶ Muchos métodos se agregaron para manipular arreglos en ES6


▶ Dado que vamos a trabajar con arreglos con frecuencia en JavaScript, es preferible
usar estos métodos optimizados para el rendimiento en lugar de crear los propios
▶ El uso de estos métodos estándar también hace que el código sea más consistente
y legible para otros desarrolladores

428/697
Find

▶ find: permite tomar la primera instancia de un elemento de un arreglo que


coincida con sus criterios de búsqueda
const items = [
{ name: 'jon', age: 20 },
{ name: 'linda', age: 22 },
{ name: 'jon', age: 40 }
];
const jon = items.find((item) => {
return item.name === 'john';
});
console.log(jon);
▶ Puede ver en la salida que devuelve el primer elemento john encontrado

429/697
Filter

▶ filter: filter es similar a find excepto que devuelve todos los elementos que
coinciden con un criterio de búsqueda
var filterItems = [
{ name: 'jon', age: 20 },
{ name: 'linda', age: 22 },
{ name: 'jon', age: 40 }
];
var results = filterItems.filter(function (item, index) {
return item.name === 'john';
});
console.log(results);
▶ La función filter también puede tomar un segundo parámetro opcional para el
número de índice del elemento del arreglo
▶ Similar a como funciona find en el sentido de que hay una verificación para ver si
se encuentra una determinada coincidencia
▶ Sin embargo, para el filtro, se devuelven todas las coincidencias

430/697
Map

▶ map: se utiliza con frecuencia en la creación de componentes de React para crear


una colección de elementos de componentes a partir de una matriz de datos
var employees = [
{ name: 'tim', id: 1 },
{ name: 'cindy', id: 2 },
{ name: 'rob', id: 3 }
];
var elements = employees.map(function (item, index) {
return '<div>' + index + ' ' + item.id + ' - ' + item.name + '</div>';
});
console.log(elements);
▶ La función map tiene dos parámetros, item e index y asigna valores de retorno
personalizados a cada elemento del arreglo

431/697
Reduce

▶ reduce: La función de reducción toma cada elemento del arreglo y, según la lógica
personalizada, crea un único valor final
const allTrucks = [ 2, 5, 7, 10 ];

const initialCapacity = 0;
const allTonnage = allTrucks.reduce((totalCapacity,
currentCapacity) => {
totalCapacity = totalCapacity + currentCapacity;
return totalCapacity;
}, initialCapacity);

console.log(allTonnage);

432/697
Otros ejemplos

// Make a copy of an array with null elements removed.


let filtered = [ 1, null, 2, 3 ].filter(x => x !== null); // filtered == [ 1, 2, 3 ]
// Square some numbers:
let squares = [ 1, 2, 3, 4 ].map(x => x * x); // squares == [ 1, 4, 9, 16 ]

console.log(filtered);
console.log(squares);

433/697
Laboratorio práctico - Programacion funcional Labs

Es momento de programar con funciones


▶ Arreglos
▶ find
▶ filter
▶ map
▶ reduce

434/697
Programación Web: HTML y CSS

Programación Web:
HTML y CSS
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

435/697
Programación Web: HTML y CSS

Introducción a las Tecnologías WEB

436/697
HTML

▶ HTML (Hypertext Markup Language)


▶ HTML = Hypertext + MarkUp
▶ Hypertext: Es texto ordinario al que se le incorporan funcionalidades adicionales
como:
▶ Formato
▶ Imágenes
▶ Multimedia
▶ Enlaces a otros documentos
▶ MarkUp: Es el proceso de tomar el texto ordinario e incorporarle símbolos
adicionales. Cada uno de estos símbolos identifica a un comando que le indica al
navegador como mostrar ese texto

437/697
El W3C

▶ El W3C (World Wide Web Consortiun) es un consorcio internacional donde


Organizaciones miembro, Personal Full-time y el público en general trabajan para
desarrollar Estándares Web
▶ La misión del W3C es la de maximizar el potencial de la WWW desarrollando
protocolos y guías que aseguren el crecimiento futuro de la Web
▶ Algunas Organizaciones miembro del W3C: Adobe, Ericsson, Nokia, Apple,
Google, inc., Opera Software, AT&T, HP, Sun Microsystems, Cisco, IBM
Corporation, Telefónica de España, Citigroup, Microsoft, Yahoo, inc., Deutsche
Telekom, Mozilla Foundation, VeriSign
▶ …y decenas de universidades de todo el mundo

438/697
¿Qué es HTML?

▶ Lenguaje de marcas
▶ Al ser texto plano es posible utilizar cualquier editor de textos para desarrollar
▶ Ejemplo de un documento HTML:
<!DOCTYPE html>
<html>
<head>
<title>Primer ejemplo en HTML</title>
</head>
<body>
<h1>Mi colección de discos</h1>
<h2>Grupo 1</h2>
<p>Descripción del grupo</p>
<ol>
<li>Disco 1</li>
<li>Disco 2</li>
</ol>
</body>
</html>

439/697
Elementos HTML
▶ Los elementos son los componentes fundamentales del HTML
▶ Cuentan con dos propiedades básicas:
▶ Atributos
▶ Contenido
▶ En general se conforman con una etiqueta de apertura y otra cierre
▶ Los atributos se colocan dentro la etiqueta de apertura, y el contenido se coloca
entre la etiqueta de apertura y la de cierre

440/697
Atributos

▶ Los atributos de un elemento son pares de nombres y valores separados por un ’=’
que se encuentran dentro de la etiqueta de apertura de algún elemento
▶ Los valores deben estar entre comillas
▶ Ejemplos:
<span id="id_de_este_elemento" style="color: red;" title="Curso de HTML">
Curso de HTML
</span>

<a href="http://www.fceia.unr.edu.ar" class="milink" target="_blank">


Universidad Nacional De Rosario
</a>

441/697
Tipos de Elementos

▶ Los elementos se pueden clasificar según su tipo:


▶ Estructurales
▶ Describen el propósito del texto y no denotan ningún formato específico
▶ Por ejemplo: <h1>Curso HTML</h1>
▶ De Presentación
▶ Describen la apariencia del texto, independientemente de su función
▶ Por ejemplo: <b>Curso HTML</b>
▶ Los elementos de presentación se encuentran obsoletos desde la aparición del CSS
▶ De hiperTexto
▶ Relaciona una parte del documento con otros documentos
▶ Por ejemplo:
<a href="http://www.fceia.unr.edu.ar">UNR</a>

442/697
Elementos HTML

▶ Elementos y propiedades:
▶ Títulos: <h1> </h1>, <h2> </h2>,…, <h6> </h6>
▶ Párrafos: <p> </p>
▶ Listas (ol, ul): <ol> <li> </li> <li> </li> </ol>
▶ Vínculos:
<a href="http://...">Descripción</a>
<a ref="mailto:[email protected]">Jose</a>
▶ Avance de línea: <br />
▶ Imágenes: <img scr="imagen.png" width="130" height="50" />

443/697
Elementos HTML cont

▶ Elementos y propiedades:
▶ Líneas: <hr />
▶ Texto en negritas: <strong> </strong>
▶ Tablas: <table> </table>
▶ Filas de una tabla: <tr> </tr>
▶ Celdas de una tabla: <td> </td>
▶ Encabezado de una tabla: <th> </th>
▶ Marcos (obsoletos): <frameset> </frameset> <frame> </frame>

444/697
Estructura de un documento HTML

▶ <html></html>
▶ Delimita el Documento HTML
▶ Cabecera: <head> </head>
▶ Título de la página: <title> </title>
▶ Meta-tags: <meta http-equiv="Content-language" content="es">
▶ Estilos: <link rel="stylesheet" href="estilo.css" media="screen"
type="text/css">
▶ Cuerpo: <body> </body> aquí se incluyen los contenidos visibles del documento
▶ <body background="imagenes/logo.gif">
▶ <body bgcolor="white">
▶ <body leftmargin="5px" bottommargin="5px">

445/697
Elementos de la cabecera

Algunos de los elementos factibles de incluir en el head son:


▶ <title> </title>
▶ Define el título del document HTML
▶ <script> </script>
▶ Se utiliza para incluir programas al documento (en general se trata código
Javascript)
▶ <style> </style>
▶ Especifica un estilo CSS para ser utilizado en el documento
▶ <meta> </meta>
▶ Permite especificar información de interés como: autor, fecha de publicación,
descripción, palabras claves, etc

446/697
Contenedores (Block-Level Elements)

▶ Párrafos
▶ Es el contenedor mas común
▶ Su sintaxis es: <p> </p>
▶ Encabezados
▶ Indican una jerarquía de secciones dentro del documento
▶ Su sintáxis: <h1> </h1>, <h2></h2>, <h3></h3>,…<h6></h6>
▶ Listas
▶ Listas de Definiciones (consiste en pares término - definición)
▶ <dl> </dl> crea la lista
▶ <dt> </dt> crea un nuevo término
▶ <dd> </dd> crea una nueva definición

447/697
Contenedores (Block-Level Elements)

▶ Lista Ordenada
▶ <ol> </ol>: Crea una nueva lista
▶ <li> </li>: Crea un nuevo ítem en la lista
▶ Lista sin ordenada
▶ <ul> </ul>: Crea una nueva lista
▶ <li> </li>: Crea un nuevo ítem en la lista
▶ Capas
▶ Permiten agrupar y diagramar contenidos en los documentos
▶ Su sintaxis es: <div> </div>

448/697
Tablas en HTML

▶ Se utilizan cuando es necesario mostrar información tabulada al usuario


▶ Ejemplo de estructura de tabla:
<table>
<tr>
<td>Celda 1, linea 1</td>
<td>Celda 2, linea 1</td>
</tr>
<tr>
<td>Celda 1, linea 2</td>
<td>Celda 2, linea 2</td>
</tr>
</table>
▶ El resultado:
Celda 1, linea 1 Celda 2, linea 1
Celda 1, linea 2 Celda 2, linea 2

449/697
Tablas en HTML cont.

▶ <table> ... </table>: Crea la tabla


▶ <tr> ... </tr>: Crea una nueva fila
▶ <td> ... </td>: Crea una nueva celda dentro de la fila
▶ Por ejemplo, para crear una tabla de 2 x 2:
<table>
<tr>
<td> ... </td>
<td> ... </td>
</tr>
<tr>
<td> ... </td>
<td> ... </td>
</tr>
</table>

450/697
Formularios

▶ Un formulario HTML permite que el usuario ingrese datos y que estos sean
enviados al servidor
▶ Normalmente los datos serán almacenados en una base de datos

451/697
Formularios

▶ Para crear un formulario utilizamos la etiqueta form:


<body>
<form action="procesar" method="POST" id="form1" name="form1">
<!-- Contenido del formulario -->
</form>
</body>

452/697
Formularios

▶ Propiedades
▶ name: Nombre con que lo referenciamos
▶ action: que quermos hacer con los datos
▶ method: método para mover los datos (get/post)
▶ enctype: Tipo de contenido de los datos
<html>
<head>
<title>Primer ejemplo en HTML</title>
</head>
<body>
<form method="POST" action="mailto:[email protected]" enctype="text/plain">
<input .../>
</form>
</body>
</html>

453/697
Formularios

▶ Elementos de formularios
▶ input
▶ text
▶ password
▶ checkbox
▶ radio
▶ submit
▶ rest
▶ file
▶ hidden
▶ image
▶ button
▶ textarea
▶ select
▶ button

454/697
Formularios
▶ text
<input type="text" value="Valor" size=NN maxlength=NN />
▶ password
<input type="password" value="Valor" size=NN maxlength=NN />
▶ radio
<input type="radio" name="tipoDocumento" value="DNI" checked /> DNI
<input type="radio" name="tipoDocumento" value="LE" /> LE
▶ checkbox
<input type="checkbox" name="airBa" value="SI" checked /> Airbag
<input type="checkbox" name="direccion" value="NO" /> Dirección asistida
▶ hidden
<input type="hidden" name="direccion" value="NO" />
▶ file
<input type="file" name="fileName" />
▶ image
<input type="image" src="submit.png" alt="Enviar" width="94" height="26" />
455/697
Formularios

Lista desplegable
▶ <select>...</select>
<html>
<head>
<title>Taller de programación</title>
</head>
<body>
<form method="POST" action="mailto:[email protected]" enctype="text/plain">
<select name="tipoDocumento">
<option value="DNI" selected>DNI</option>
<option value="LE">Libreta de Enrolamiento</option>
<option value="LC">Libreta Civica</option>
<option value="PASAPORTE">Pasaporte</option>
</select>
</form>
</body>
</html>

456/697
Formularios

Lista enrollable
▶ select incluyendo el atributo ”size”
<html>
<head>
<title>Taller de programación</title>
</head>
<body>
<form method="POST" action="mailto:[email protected]" enctype="text/plain">
<select name="tipoDocumento" size="3">
<option value="DNI" selected>DNI</option>
<option value="LE">Libreta de Enrolamiento</option>
<option value="LC">Libreta Civica</option>
<option value="PASAPORTE">Pasaporte</option>
</select>
</form>
</body>
</html>

457/697
Formularios

Area de Texto
<html>
<head>
<title>Taller de programación</title>
</head>
<body>
<form method="POST" action="mailto:[email protected]" enctype="text/plain">
<textarea name="Comentario" cols="60" rows="5" wrap="soft">
</textarea>
</form>
</body>
</html>

458/697
Formularios cont.

▶ Enviar y resetear un formulario


<input type="submit" name="nombre1" value="Presione aquí para
enviar" />
<input type="reset" name="nombre2" value="Presione aquí para
resetear" />

459/697
Programación Web: HTML y CSS

HTML Semantico

460/697
Elementos de estructura

▶ <header>: Encabezado. Puede contener otros elementos


▶ <nav>: Navegación del sitio
▶ <article>: Componentes independientes de la página
▶ <section>: Organización de contenidos
▶ <aside>: Componentes complementarios
▶ <footer>: Pie de páginaComo crear tablas con elementos básicos

461/697
Ejemplo de estructura antes de HTML 5

462/697
Ejemplo de estructura con HTML 5

463/697
Información adicional

▶ https://htmlcheatsheet.com/
▶ http://html5doctor.com/downloads/h5d-sectioning-flowchart.pdf

464/697
Programación Web: HTML y CSS

Cascading Style Sheets (CSS)

465/697
Selectores

▶ Los selectores se utilizan para identificar a que elementos se le aplican las reglas
de CSS
▶ Existen distintos tipos de selectores, los cuales se detallan a continuación

466/697
Selectores

▶ Selector universal: es el asterisco, y se aplica a todos los tipos de elementos en el


documento
▶ En general se utiliza para valores por defecto
* { }

467/697
Selectores

▶ Selector de tipo: se aplica a todos los elementos especificados en una lista


delimitada por coma
▶ Permite aplicar las mismas reglas a varios elementos
h1, h2, h3 { }

468/697
Selectores

▶ Selector de clase: se aplica a un elemento (o elementos) que contenga el atributo


class cuyo valor concuerde con el que se especifico en el selector de clase
▶ Se puede utilizar de dos formas
▶ Asignando una regla que se aplique a cualquier elemento cuyo valor sea el
especificado en el selector
▶ Asignando una regla que se aplique a un único elemento cuyo valor sea el
especificado en el selector

469/697
Selectores

▶ Por ejemplo: <p class="backgroundNote">Nota de fondo</p>


▶ Utilizando la primer forma sería:
.backgroundNote { }
▶ Utilizando la segunda forma sería:
p.backgroundNote { }

470/697
Selectores

▶ Un atributo class puede contener más de un valor separados por un espacio:


<p class="important code">Código importante</p>
▶ La siguiente sintaxis se utiliza para indicar que un elemento que contenga un
atributo class debe contener ambos valores:
p.important.code { }

471/697
Selectores

▶ Selector de id: se utiliza al igual que el selector de clase, pero trabaja sobre el
valor del atributo id
▶ Se utiliza el signo cardinal #
▶ Dado que el valor del atributo id debe ser único dentro de un documento, este
selector se aplica al contenido de dicho elemento

472/697
Selectores

▶ Selector hijo: se aplica al elemento que es hijo directo de otro elemento


▶ Los nombre de ambos elementos estan separados por el signo mayor (>)
▶ Al signo que representa al selector se lo conoce como combinador
td > b { }

473/697
Selectores

▶ Selector descendiente: se aplica al elemento que es descendiente de otro elemento


especificado
▶ No tiene por que ser un descendiente directo
▶ El combinador es el espacio
table b { }

474/697
Selectores

▶ Selector adyacente: se aplica al elemento siguiente de otro elemento especificado


▶ El combinador es el signo más (+)
h1+p { }

475/697
Selectores

▶ Selector hermano posterior


▶ El combinador es el signo más (~)
h1~p{}

476/697
Selectores

▶ Selector de atributo: permite utilizar los atributos de un elemento y sus valores


como selectores
▶ Algunos de estos selectores pertenecen a CSS3

477/697
Selectores

▶ Selectores de atributo:
▶ Selector de existencia: p[id]
▶ Selector de igualdad: p[id="summary"]
▶ Selector de espacio: p[class~="XHTML"]
▶ Selector guión: p[language|="en"]
▶ Selector prefijo (CSS3): p[attr^="b"]
▶ Selector substring (CSS3): p[attr*="on"]
▶ Selector sufijo (CSS3): p[attr$="x"]

478/697
Lengths

▶ Hay tres formas de especificar el largo de una propiedad en CSS:


▶ Unidades relativas
▶ Unidades absolutas
▶ Unidades relativas

479/697
Unidades relativas

▶ Hay tres tipos de unidades relativas:


▶ Pixel:
▶ relativo a la resolución de pantalla
▶ se especifica con px
▶ em’s:
▶ relativo al tamaño de las fuentes
▶ equivalente al alto de la fuente actual
▶ ex’s:
▶ relativo al tamaño de las fuentes
▶ es el alto de la x minuscula

480/697
Unidades absolutas

▶ Las unidades relativas son las siguientes:


▶ Un punto (pt)
▶ Una pica (pc)
▶ Una pulgada (in)
▶ Un centímetro (cm)
▶ Un milímetro (mm)
▶ Son menos utilizadas que las unidades relativas

481/697
Introducción al modelo de caja

▶ El modelo de caja (box model) es un concepto importante en CSS dado que


determina como son posicionados los elementos dentro de la ventana del
navegador
▶ Cada caja tiene propiedades a tener en cuenta:
▶ border
▶ margin
▶ padding

482/697
Document Object Model (DOM)

Document Object
Model (DOM)
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

483/697
Document Object Model (DOM)

Introducción

484/697
¿Qué es el DOM?

▶ El DOM define una forma estándar para acceder y manipular documentos HTML
▶ El DOM presenta un documento HTML como una estructura de árbol

485/697
¿Qué es el DOM? cont.

▶ El DOM es un estándar W3C (World Wide Web Consortium)


▶ El DOM define un estándar para acceder a documentos HTML y XML:
”El modelo de objetos de documento (DOM) del W3C es una plataforma y una
interfaz neutral en el lenguaje que permite que los programas y scripts accedan y
actualicen dinámicamente el contenido, la estructura y el estilo de un documento.”
▶ El estándar W3C DOM se divide en 3 partes diferentes:
▶ Core DOM: modelo estándar para cualquier documento estructurado
▶ XML DOM - modelo estándar para documentos XML
▶ HTML DOM - modelo estándar para documentos HTML

486/697
¿Qué es el DOM? cont.

▶ El DOM es:
▶ Un modelo de objetos estándar para HTML
▶ Una interfaz de programación estándar para HTML
▶ Un estándar W3C
▶ El DOM define los objetos y las propiedades de todos los elementos HTML y los
métodos para acceder a ellos
▶ En otras palabras:
▶ El DOM es un estándar sobre cómo obtener, cambiar, agregar o eliminar elementos
HTML

487/697
Ejemplo

<!DOCTYPE html>
<html>
<body>
<script>
function changeImage() {
element = document.getElementById('myimage');
if (element.src.match('bulbOn')) {
element.src = 'pic_bulbon.png';
} else {
element.src = 'pic_bulboff.png';
}
}
</script>
<img id="myimage" onclick="changeImage()"
src="pic_bulboff.png" width="100" height="180" />
<p>Click to turn on/off the light</p>
<body>
</html>

488/697
Nodos DOM

En DOM, todo es un nodo. El DOM es HTML visto como un árbol de nodos


▶ Nodos DOM
▶ De acuerdo con el estándar W3C HTML DOM, todo en un documento HTML es un
nodo:
▶ Todo el documento es un nodo de documento
▶ Cada elemento HTML es un nodo de elemento
▶ El texto dentro de los elementos HTML son nodos de texto
▶ Cada atributo HTML es un nodo de atributo
▶ Los comentarios son nodos de comentarios

489/697
Árbol de nodos DOM

▶ El HTML DOM ve los documentos HTML como estructuras de árbol


▶ La estructura se llama árbol de nodos:

490/697
Árbol de nodos DOM cont.

▶ Con DOM, se puede acceder a todos los nodos del árbol mediante JavaScript
▶ Todos los elementos HTML (nodos) se pueden modificar y los nodos se pueden
crear o eliminar

491/697
Nodo padres, hijos y hermanos

▶ Los nodos en el árbol de nodos tienen una relación jerárquica entre sí


▶ Los términos padre, hijo y hermano se utilizan para describir las relaciones
▶ Los nodos padres tienen hijos
▶ Los hijos en el mismo nivel se llaman hermanos
▶ En un árbol de nodos, el nodo superior se llama raíz
▶ Cada nodo tiene exactamente un padre, excepto la raíz (que no tiene padre)
▶ Un nodo puede tener cualquier número de hijos
▶ Los hermanos son nodos con el mismo padre

492/697
Nodo padres, hijos y hermanos cont.

▶ La siguiente imagen ilustra una parte del árbol de nodos y la relación entre los
nodos:

493/697
Nodo padres, hijos y hermanos cont.

▶ Veamos el siguiente fragmento de HTML:


<html>
<head>
<title>DOM Tutorial</title>
</head>
<body>
<h1>DOM Lesson one</h1>
<p>Hello World!</p>
</body>
</html>

494/697
Nodo padres, hijos y hermanos cont.

▶ Del HTML anterior:


▶ El nodo <html> no tiene un nodo principal; es el nodo raíz
▶ El nodo padre de los nodos <head> y <body> es el nodo <html>
▶ El nodo padre de ”Hello World!” el nodo de texto es el nodo <p>
▶ and:
▶ El nodo <html> tiene dos nodos hijos: <head> y <body>
▶ El nodo <head> tiene un nodo hijo: el nodo <title>
▶ El nodo <title> también tiene un nodo hijo: el nodo de texto ”Tutorial DOM”
▶ Los nodos <h1> y <p> son hermanos y nodos hijos de <body>
▶ and:
▶ El elemento <head> es el primer hijo del elemento <html>
▶ El elemento <body> es el último hijo del elemento <html>
▶ El elemento <h1> es el primer hijo del elemento <body>
▶ El elemento <p> es el último hijo del elemento <body>

495/697
Advertencia!

▶ Un error común en el procesamiento de DOM es esperar que un nodo de elemento


contenga texto
▶ En este ejemplo: <title>DOM Tutorial</title>, el nodo de elemento
<title>, contiene un nodo de texto con el valor ”DOM Tutorial”
▶ Se puede acceder al valor del nodo de texto mediante la propiedad innerHTML del
nodo

496/697
Métodos DOM

▶ Los métodos son acciones que puede realizar en los nodos (Elementos HTML)
▶ Interfaz de programación
▶ Se puede acceder al DOM con JavaScript (y otros lenguajes de programación)
▶ Todos los elementos HTML se definen como objetos, y la interfaz de programación
son los métodos y las propiedades del objeto
▶ Un método es una acción que puede realizar (como agregar o modificar un elemento)
▶ Una propiedad es un valor que puede obtener o establecer (como el nombre o el
contenido de un nodo)

497/697
Objetos DOM - Métodos y propiedades

▶ Algunos métodos DOM de uso común:


▶ getElementById(id) - obtener el nodo (elemento) con una identificación específica
▶ appendChild(node) - insertar un nuevo nodo hijo (elemento)
▶ removeChild(node) - eliminar un nodo hijo (elemento)
▶ Algunas propiedades DOM de uso común:
▶ innerHTML - el valor de texto de un nodo (elemento)
▶ parentNode - el nodo padre de un nodo (elemento)
▶ childNodes - los nodos hijos de un nodo (elemento)
▶ attributes - los nodos de atributos de un nodo (elemento)

498/697
Algunos métodos del objeto DOM

▶ getElementsByTagName(): Devuelve una lista de nodos (colección/matriz de


nodos) que contiene todos los elementos con un nombre de etiqueta especificado
▶ getElementsByClassName(): Devuelve una lista de nodos que contiene todos
los elementos con una clase específica
▶ replaceChild(): Reemplaza un nodo hijo
▶ insertBefore(): Inserta un nuevo nodo hijo antes de un nodo hijo especificado
▶ createAttribute(): Crea un nodo de atributo
▶ createElement(): Crea un nodo Elemento
▶ getAttribute(): Devuelve el valor del atributo especificado
▶ setAttribute(): Establece o cambia el atributo especificado, al valor
especificado

499/697
La propiedad innerHTML

▶ La forma más sencilla de obtener el contenido de un elemento es mediante la


propiedad innerHTML
▶ La propiedad innerHTML es útil para obtener o reemplazar el contenido de los
elementos HTML
<html>
<body>
<p id="intro">Hello World!</p>
<script>
var txt = document.getElementById("intro").innerHTML;
document.write(txt);
</script>
</body>
</html>

500/697
La propiedad del nodoValue

La propiedad nodeValue especifica el valor de un nodo


▶ nodeValue para los nodos de elementos no está definido
▶ nodeValue para nodos de texto es el texto mismo
▶ nodeValue para los nodos atributo es el valor del atributo

501/697
Obtener el valor de un elemento

<!DOCTYPE html>
<html>
<body>
<p id="intro">Hello World!</p>
<script>
x = document.getElementById("intro");
document.write(x.firstChild.nodeValue);
</script>
</body>
</html>

502/697
Acceso a elementos HTML (nodos)

▶ Puede acceder a un elemento HTML de diferentes maneras:


▶ Usando el método getElementById() (como vimos en la diapositiva anterior)
▶ Usando el método getElementsByTagName()
▶ getElementsByTagName() devuelve todos los elementos con un nombre de etiqueta
especificado
▶ Usando el método getElementsByClassName()
▶ Para encontrar todos los elementos HTML con el mismo nombre de clase

503/697
El método getElementsByTagName()

<!DOCTYPE html>
<html>
<body>
<p>Hello World!</p>
<p>The DOM is very useful!</p>
<p>This example demostrates the <b>getElementByTagName</b> method.</p>
<script>
x = document.getElementByTagName("p");
docuemnt.write("Text of first partagraph: " + x[0].innertHTML);
</script>
</body>
</html>

504/697
Modificar elementos HTML

▶ Modificar el DOM se puede interpretar de diferentes maneras


▶ Cambiar el contenido HTML
▶ Cambiar estilos CSS
▶ Cambiar atributos HTML
▶ Creación de nuevos elementos HTML
▶ Eliminar elementos HTML existentes
▶ Cambiar eventos (controladores)

505/697
Cambiar el contenido HTML

▶ La forma más fácil de cambiar el contenido de un elemento es usando la


propiedad innerHTML
<p id="p1">Hello World!</p>

<script>
document.getElementById("p1").innerHTML = "New text!";
</script>

506/697
Cambiar el estilo HTML

▶ Con DOM podemos acceder al objeto style de los elementos HTML


<p id="p2">Hello world!</p>

<script>
document.getElementById("p2").style.color="blue";
</script>

507/697
Creando nuevos elementos HTML

▶ Para agregar un nuevo elemento al DOM, primero debe crear el elemento (nodo)
y luego agregarlo a un elemento existente
<!DOCTYPE html>
<html>
<body>
<div id="div1">
<p id="p1">This is a paragraph.</p>
<p id="p2">This is another paragraph.</p>
</div>
<script>
var para = document.createElement("p");
var node = document.createTextNode("This is new.");
para.appendChild(node);

var element = document.getElementById("div1");


element.appendChild(para);
</script>
</body>
</html>

508/697
Usando events

▶ El DOM nos permite ejecutar código cuando ocurre un evento


▶ Los eventos son generados por el navegador cuando ”suceden cosas” sobre los
elementos HTML:
▶ Se hace clic en un elemento
▶ La página ha cargado
▶ Los campos de entrada se cambian

509/697
Usando eventos cont.

▶ Ejemplo 1:
<input
type="button"
onclick="document.body.style.backgroundColor='lavender';"
value="Change background color"
/>
▶ Ejemplo 2:
<script>
function ChangeBackground() {
document.body.style.backgroundColor="lavender";
}
</script>

<input
type="button"
onclick="ChangeBackground()"
value="Change background color"
/>

510/697
Reacción a eventos (usando JavaScript)

▶ JavaScript se puede ejecutar cuando ocurre un evento, por ejemplo cuando un


usuario hace clic en un elemento HTML
▶ Para ejecutar código cuando un usuario hace clic en un elemento, agregue código
JavaScript a un atributo de evento HTML: onclick="código JavaScript"
▶ Algunos ejemplos de eventos HTML:
▶ Cuando un usuario hace clic con el mouse
▶ Cuando una página web ha cargado
▶ Cuando el mouse se mueve sobre un elemento
▶ Cuando se cambia un campo de entrada
▶ Cuando se envía un formulario HTML
▶ Cuando un usuario pulsa una tecla

511/697
Los eventos onmouseover y onmouseout

<!DOCTYPE html>
<html>
<body>
<div onmouseover="mOver(this)" onmouseout="mOut(this)"
style="background-color: #D94A38; width: 120px; height: 20px; padding: 40px;">
Mouse Over Me
</div>
<script>
function mOver(obj) {
obj.innerHTML = "Thank You";
}

function mOut(obj) {
obj.innerHTML = "Mouse Over Me";
}
</script>
</body>
</html>

512/697
Los eventos onmousedown, onmouseup y onclikc

<!DOCTYPE html>
<html>
<body>
<div onmousedown="mDown(this)" onmouseup="mUp(this)"
style="background-color: #D94A38; width: 90px; height: 20px; padding: 40px;">
Click Me
</div>
<script>
function mDown(obj) {
obj.style.backgroundColor = "#1EC5E5";
obj.innerHTML = "Release Me";
}

function mUp(obj) {
obj.style.backgroundColor = "#D94A38";
obj.innerHTML = "Thank You";
}
</script>
</body>
</html>

513/697
Accesibilidad

Accesibilidad
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

514/697
Accesibilidad

Accesibilidad

515/697
¿Qué es la Accesibilidad Web?

▶ Definición: La cualidad de ser fácil de obtener, usar, comprender, alcanzar o


ingresar
▶ La práctica inclusiva de eliminar las barreras que impiden la interacción o el
acceso a los sitios Web por parte de las personas con discapacidad

516/697
Tecnología de asistencia

▶ Cualquier artículo, equipo o sistema, ya sea adquirido comercialmente, modificado


o personalizado, que se utiliza para aumentar, mantener o mejorar las capacidades
funcionales de las personas con discapacidades
▶ Ejemplos:
▶ Lectores de pantalla
▶ Dispositivos señaladores
▶ Interruptores
▶ Teclados alternativos
▶ Siri, Amazon Echo, etc.

517/697
Métodos de acceso alternativos

▶ Teclados alternativos
▶ Ratones de un solo botón
▶ Bolas de seguimiento/Joysticks
▶ Dispositivos para señalar de cabeza
▶ Asistentes para señalar/escribir
▶ Interruptores/Teclados en pantalla
▶ Ventanas táctiles

518/697
Los dispositivos señaladores de baja tecnología pueden incluir

▶ Punteros de cabeza/barbilla
▶ Lápices
▶ Punteros de mano adaptados
▶ Palos de boca

519/697
Web Content Accessibility Guidelines (WCAG) 2.0

▶ (WCAG) 2.0 define cómo hacer que el contenido web sea más accesible para las
personas con discapacidades
▶ La accesibilidad implica una amplia gama de discapacidades, incluidas
discapacidades visuales, auditivas, físicas, del habla, cognitivas, del lenguaje, de
aprendizaje y neurológicas
▶ Aunque estas pautas cubren una amplia gama de temas, no pueden abordar las
necesidades de las personas con todos los tipos, grados y combinaciones de
discapacidad
▶ Estas pautas también hacen que el contenido Web sea más utilizable por personas
mayores con habilidades cambiantes debido al envejecimiento y, a menudo,
mejoran la usabilidad para los usuarios en general

520/697
WCAG 2.0

▶ Los cuatro principios rectores de la accesibilidad en las WCAG 2.0


▶ Perceptible
▶ Operable
▶ Comprensible
▶ Robusto
▶ Estos principios (a veces denominados ”POUR” permanecen constantes a medida
que cambia la tecnología
▶ Cada principio contiene pautas, que a su vez contienen varios criterios de éxito
▶ Los principios se examinan en profundidad en Construcción de un sitio Web
POUR https://webaim.org/articles/pour/

521/697
Niveles de conformidad

▶ Para ayudar a los equipos de desarrollo a priorizar la implementación de la


accesibilidad y los esfuerzos de corrección, los criterios de éxito de las WCAG se
organizan en tres niveles de conformidad:
▶ Nivel A: es un requisito básico para que algunos usuarios con discapacidad puedan
acceder y utilizar el contenido web
▶ Nivel AA: indica accesibilidad general y elimina de barreras significativas para
acceder al contenido
▶ Nivel AAA: proporciona mejoras a la accesibilidad Web para algunos usuarios con
discapacidades

522/697
Niveles de conformidad

▶ Estos niveles son acumulativos


▶ Para reclamar la conformidad con el Nivel AA, un sitio web debe cumplir con todos
los criterios de éxito del Nivel A y AA
▶ Asimismo, la conformidad con el Nivel AAA implica que se han cumplido todos los
criterios de éxito de los tres niveles
▶ La mayoría de los sitios web deben apuntar a la conformidad con el Nivel AA
▶ Dependiendo de los usuarios objetivo, algunos criterios de éxito del nivel AAA,
como el nivel de lectura, el contraste (mejorado), el tamaño del objetivo u otros,
pueden ser beneficiosos de implementar
▶ Muy pocos sitios web pueden reclamar la conformidad total del nivel AAA, ¡ni
siquiera webaim.org o el sitio web de WCAG en sí!

523/697
Sección 508

▶ Aplica para el gobierno federal


▶ Adoptado como parte de la Enmienda de 2001 a la Ley de Rehabilitación
▶ Basado inicialmente en WCAG 1.0 (Mayo de 1999)

524/697
WCAG 2.0 frente a la Sección 508

▶ Los criterios de éxito de las WCAG 2.0 son más explícitos que los estándares 508
existentes.
▶ WCAG 2.0 está escrito de una manera que es tecnológicamente neutral y, por lo
tanto, es directamente aplicable a una amplia gama de tipos y formatos de
contenido
▶ WCAG 2.0 tiene 38 criterios de éxito de nivel A y AA
▶ De estos, 22 están redactados de manera diferente pero equivalentes en esencia a
los requisitos actuales de 508
▶ La Sección 508 está en proceso de actualización para alinearse con WCAG 2.0
(nivel AA)

525/697
WCAG 2.1

▶ WCAG 2.1, la subversión actual de WCAG 2, se adoptó en 2018


▶ No reemplazó a WCAG 2.0 de la misma manera que WCAG 2.0 reemplazó a 1.0
▶ En cambio, agrega 28 nuevos criterios de éxito, especialmente en el área de
dispositivos móviles
▶ Todos los criterios de éxito de 2.0 permanecen sin cambios, al igual que los cuatro
principios básicos

526/697
Espectro de discapacidades

▶ Visual
▶ Auditivo
▶ Físico
▶ Cognitivo
▶ Discurso

527/697
Ejemplos de Buenas Prácticas para Discapacidades Visuales

▶ Las imágenes y los controles deben tener alternativas de texto equivalentes


(atributo alt)
▶ El texto, las imágenes y los diseños de página se pueden cambiar de tamaño sin
perder información
▶ El contenido de video tiene alternativas de texto o audio, o una pista de
descripción de audio
▶ El texto y las imágenes tienen suficiente contraste entre el color de primer plano y
el de fondo
▶ Proporcionar una navegación consistente y predecible
▶ Evitar usar solo el color para identificar enlaces o controles

528/697
Discapacidades auditivas

▶ Problemas de audición
▶ Sordera

529/697
Ejemplos de buenas prácticas para discapacidades auditivas

▶ El contenido de audio, incluidos los videos, proporciona subtítulos o


transcripciones
▶ Los reproductores multimedia proporcionan controles de volumen
▶ Los reproductores multimedia brindan opciones para ajustar el tamaño y los
colores del texto de los subtítulos
▶ No incluir interacciones que dependan del uso exclusivo de la voz

530/697
Ejemplos de discapacidades físicas

▶ Amputación
▶ Artritis
▶ Fibromialgia
▶ Reumatismo
▶ Distrofia muscular
▶ Lesión por estrés repetitivo
▶ Temblores y espasmos
▶ Cuadriplejia

531/697
Buenas prácticas para discapacidades físicas

▶ Proporcionar soporte completo de teclado


▶ Todos los enlaces, elementos de menú, controles deben ser accesibles a través del
teclado (tecla tabulador, mayús+tabulador y retorno)
▶ Proporcionar un tiempo suficiente para completar las tareas
▶ Proporcionar funciones de páginación y navegación consistentes, predecibles y
simples
▶ Elementos de enlace y botones deben tener un tamaño suficiente

532/697
Ejemplos de discapacidades cognitivas

▶ Trastorno por déficit de atención con hiperactividad (TDAH)


▶ Trastorno del espectro autista (TEA)
▶ Alteraciones de la memoria
▶ Esclerosis múltiple
▶ Trastornos de la percepción o del aprendizaje
▶ Trastornos convulsivos

533/697
Buenas prácticas para los trastornos cognitivos

▶ Proporcione diseños de página y navegación simples que sean fáciles de entender y


usar
▶ Evite, cuando sea posible, oraciones complejas que sean difíciles de leer o palabras
inusuales
▶ Evite el mover o parpadear del contenido o proporcione un método para
deshabilitarlo
▶ El contenido de video, animaciones o audio se deben poder pausar o detener
▶ El texto simple se complementa con imágenes, gráficos o ilustraciones

534/697
Comprobación de la accesibilidad

▶ Prueba manual
▶ Comprobación del teclado
▶ Uso con lector de pantalla
▶ Herramientas en línea
▶ WebAIM WAVE https://wave.webaim.org/

535/697
Temas potenciales

▶ Accesibilidad Recursos/Herramientas
▶ Imágenes y texto alternativo y contraste
▶ Accesibilidad de PDF
▶ Lectores de pantalla (de escritorio y móviles)
▶ Accesibilidad del teclado

536/697
Mas información

▶ https://www.w3.org/TR/WCAG/
▶ https://www.section508.gov/
▶ https://www.access-board.gov/ict/wcag2ict.html
▶ https://www.w3.org/TR/WCAG21/
▶ https://www.w3.org/WAI/fundamentals/
▶ https://www.w3.org/WAI/standards-guidelines/wcag/

537/697
Accesibilidad

HTML y ARIA

538/697
¿Qué es ARIA?

▶ Hoy en día, como mejor práctica, los desarrolladores Web utilizan HTML
semántico al construir sitios y páginas Web
▶ El HTML semántico es donde se utilizan los elementos HTML más apropiados y
descriptivos, ayudando a los robots, a los servicios y a aquellos que dependen de
las tecnologías de asistencia (AT) a comprender el significado del contenido
▶ ARIA va un paso más allá, agregando un conjunto de atributos que ayudan a
definir el contenido de una página más allá de lo que el HTML puede hacer por sí
solo
▶ Estos atributos ARIA añaden caracteristicas como navegación accesible, consejos
sobre formularios, mensajes de error y otros útiles potenciadores

539/697
¿Qué son los roles de ARIA?

▶ Siempre que sea posible, se debe utilizar el HTML semántico nativo, pero se
pueden utilizar los roles ARIA para rellenar cualquier hueco
▶ Los roles ARIA son aplicados a elementos HTML usando el atributo role, y
pueden ser usados:
▶ Para describir los elementos más nuevos o conceptuales que podrían no tener un
soporte completo para el navegador o ser entendidos por los lectores de pantalla, por
ejemplo <button role="tab">Tab</button>
▶ Para ”arreglar” (lo mejor posible) el HTML implementado incorrectamente donde no
se ha usado la semántica, por ejemplo <div role="button">Button</div>

540/697
Atributo role

▶ Los roles de ARIA pueden clasificarse en 4 tipos:


▶ Roles abstractos: De acuerdo con la documentación oficial del W3C, estos son los
roles utilizados por el navegador. Son la base sobre la que se construyen todos los
demás roles de WAI-ARIA. Los autores del contenido no deben utilizar roles
abstractos porque no se implementan en la vinculación del API. Ejemplos de roles
abstractos incluyen widget, landmark, window, command, etc.
▶ Widget de Roles: Se utilizan para definir un elemento de interfaz de usuario
cuando no se utiliza el HTML semántico. Según el W3C, algunos roles de widget
sirven como interfaces de usuario independientes o actúan como parte de un widget
compuesto más grande. Algunos ejemplos de roles de los widgets son alert,
dialog, checkbox, marquee, etc. Otros roles de los widgets sirven como
contenedores que gestionan otros contenidos de widgets. Ejemplos de estos widgets
son tree, tablist, menu, menubar, etc.

541/697
Atributo role cont.

▶ Roles de estructura de documentos: Se trata de funciones que describen las


estructuras que organizan el contenido de una página y que no suelen ser
interactivas. Roles como estos ayudan a las tecnologías de asistencia a identificar
y clasificar las diferentes secciones de una página. Algunos ejemplos son article,
toolbar, row, list, etc.
▶ Roles Landmark: Identifican grandes áreas de contenido. Esto ayuda a las
tecnologías de asistencia a definir estas secciones a los usuarios que dependen de
ellas. Ejemplos de funciones de referencia son application, form, main, etc.

542/697
¿Qué son los estados y propiedades de ARIA?
▶ Los estados y propiedades de ARIA proporcionan apoyo a los roles de ARIA que
existen en una página
▶ Cuando se combinan con los roles, pueden suministrar tecnologías de asistencia
con información adicional de la interfaz de usuario
▶ Siempre que hay cambios en los estados o propiedades, las tecnologías de
asistencia son notificadas de este cambio para que puedan alertar al usuario de
que se ha producido un cambio
▶ Las propiedades de ARIA se diferencian de los estados en que el valor de una
propiedad (como aria-labelledby) suele ser menos probable que cambie a lo
largo del ciclo de vida de la aplicación, mientras que es probable que un estado
(por ejemplo, aria-checked) cambie con bastante frecuencia debido a la
interacción del usuario
▶ Las propiedades y estados de ARIA pueden clasificarse como:
▶ Atributos del Widget
▶ Atributos de las regiones vivas
▶ Atributos de arrastrar y soltar
▶ Atributos de la relación 543/697
Atributos del Widget

▶ Estos tipos de atributos se utilizan para los elementos comunes de la interfaz de


usuario que reciben las aportaciones del usuario y procesan las acciones del usuario
▶ También se utilizan para apoyar las funciones de los widgets
▶ Entre los ejemplos figuran los siguientes: aria-readonly, aria-required,
aria-checked

544/697
Atributos del Widget cont.

▶ Usando el atributo required


<label for="field">Nombre</label>
<input required id="field" name="name" placeholder="Ej: Pedro" />
▶ Usando WAI-ARIA
<label for="field">Nombre</label>
<input required aria-required="true" id="field" name="name" placeholder="Ej: Pedro" />

545/697
Atributos de las regiones vivas

▶ Estos atributos se utilizan para indicar a un usuario que un contenido específico


puede cambiar o actualizarse (o, simplemente, que se trata de regiones vivas)
▶ Se aplican directamente sobre el elemento que cambia para que las tecnologías de
asistencia puedan notificar a los usuarios el cambio en dicho documento/página
▶ Por ejemplo, sería importante hacer uso de aria-live en un elemento que
muestra datos en vivo desde un punto final como la bolsa de valores
▶ Ejemplos de atributos como este son aria-live, aria-atomic, aria-busy y
aria-relevant

546/697
Atributos de arrastrar y soltar

▶ Se utilizan para elementos que son arrastrables o son objetivos de lanzamiento


▶ Las formas que requieren la carga de cualquier tipo de archivo (imagen,
documento pdf, etc.) a menudo utilizan el método de arrastrar y soltar para
cargar dicho archivo
▶ Es importante que no se deje de lado a los usuarios que dependen de tecnologías
de asistencia, y este tipo de atributo puede ayudar a ello
▶ Ejemplos de ello son el aria-dropeffect para los elementos que reciben el
evento de soltar y el aria-draggable para los elementos que son arrastrables

547/697
Atributos de relación

▶ Estos tipos de atributos ayudan a conectar dos elementos que son difíciles de
identificar de otra manera utilizando la estructura del documento HTML
▶ Un ejemplo de este tipo de atributo es el aria-labelledby por atributo
▶ Este atributo ayuda a conectar un campo de entrada con una etiqueta en un
formulario (pero puede utilizarse para relaciones menos obvias):
<form>
<label for="name" id="nameLabel">Name</label>
<input type="text" aria-labelledby="nameLabel" />
</form>
▶ Otros ejemplos de atributos de relación son aria-colspan, aria-controls,
aria-owns, aria-flowto, etc.

548/697
Informacion adicional

▶ https://www.w3.org/TR/wai-aria/
▶ https://www.digitala11y.com/wai-aria-1-1-cheat-sheet/
▶ https://www.digitala11y.com/accessibility-cheat-sheets/
▶ https://lab.abhinayrathore.com/aria-cheatsheet/

549/697
Sass

Sass
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

550/697
Sass

Introducción

551/697
¿Que es Sass?

▶ Sass: Syntactically Awesome Stylesheets


▶ Es un metalenguaje de hoja de estilos
▶ Basado en SassScript, que es un lenguaje de script simple

552/697
¿Que es Sass?

▶ De las pruebas que hicimos con CSS, puede que nos hemos dado cuenta de
algunos aspectos:
▶ Existen propiedades a las que asignamos una serie de valores en muchas reglas
distintas. Generalmente, atribuimos los mismos colores, fuentes, etc. a diversos
elementos
▶ Hay casos donde existen muchas reglas asignadas a sucesivos componentes hijos o
descendientes, con selectores repetitivos
▶ Sin tener demasiados estilos, podemos terminar ocupando gran cantidad de lineas
▶ Para mejorar las prestaciones de CSS, surgen los denominados preprocesadores
CSS, entre los que destacan LESS o SASS

553/697
¿Que es Sass?

Existen dos variantes sintacticas de SASS, con archivos .sass y .scss; nosotros nos
quedaremos con la segunda opcion En cualquiera de los casos, aportan las mismas
funcionalidades, pero algunas de las caracteristicas destacables de la variante SCSS son
las siguientes:
▶ Legibilidad (dada su similaridad con CSS)
▶ Suavidad de curva de aprendizaje (anadiendo pequenos detalles a CSS)
▶ Compatibilidad (un archivo CSS es un archivo valido para SCSS)
▶ Variedad de recursos disponibles, y extensibilidad (facil pasar de .scss a .sass)

554/697
¿Que es Sass?
Las principales funcionalidades que nos aporta cualquiera de estas variantes de SASS
son las siguientes:
▶ Variables: asignamos un valor a una variable, que se puede utilizar en muchas
reglas (evita repetir valores)
▶ Anidamiento de reglas, agrupando reglas dentro de otras, segun la estructura
jerarquica dada (evita repetir selectores)
▶ Mixins: funciones con las que generar reglas dependientes de parametros,
facilitando la reutilizacion de reglas
▶ Extensiones: para poder heredar propiedades y extenderlas, reutilizando en este
caso asignaciones de propiedades
▶ Operadores aritmeticos para trabajar con multiplos o divisores de ciertos valores,
entre otros
▶ Comentarios de una linea, formando parte del archivo a preprocesar pero no del
CSS final generado
555/697
¿Que es Sass?

▶ Para instalar sass podemos utilizar el gestor de paquetes npm


▶ npm install node-sass -g

556/697
Sass

Variables

557/697
Variables

▶ Las variables pueden ayudar a mantener la coherencia en todo un sitio Web


▶ En lugar de repetir los mismos valores en muchas propiedades diferentes, podemos
establecer una variable y luego utilizarla cuando la necesitemos (de cambiar el
valor, solo necesitamos hacerlo en un lugar)
▶ Si observamos el siguiente archivo Sass, contiene dos variables:
$primary-color: orange;
$secondary-color: gold;

body {
color: $primary-color;
background: $secondary-color;
}

558/697
Variables cont.

▶ Una variable se llama $primary-color y la otra se llama $secondary-color


▶ Las variables son como contenedores que almacenan un valor. En nuestro caso,
almacenamos el valor naranja en una variable y oro en la otra
▶ En lugar de escribir naranja cada vez que necesitemos usar ese color, podemos
usar el nombre de la variable. Si necesitamos actualizar un color, solo necesitamos
actualizarlo en el lugar donde configuramos la variable.

559/697
Guiones & guiones bajos

▶ Los nombres de variables pueden usar guiones y guiones bajos indistintamente


▶ Se puede acceder a nuestra variable llamada $primary-color usando
$primary_color y viceversa
▶ Entonces nuestro archivo podría verse así y aún funcionaría:
$primary_color: orange;
$secondary_color: gold;

body {
color: $primary-color;
background: $secondary-color;
}

560/697
Anidamiento
▶ Las variables también se pueden establecer dentro de un selector
▶ Por ejemplo:
header {
$header-color: orange;
color: $header-color;
}
▶ Sin embargo, tales variables solo están disponibles dentro del nivel de selectores
anidados donde están definidas
▶ Si se definen fuera de los selectores anidados, estáran disponibles en todas partes
▶ Por lo tanto, lo siguiente no funcionará:
header {
$header-color: orange;
color: $header-color;
}
article {
color: $header-color;
}
▶ Si intentamos compilar el código, recibiremos un error similar a esto:
Error: Undefined variable: "$header-color"
561/697
La bandera !global

▶ Sin embargo, el ejemplo anterior funcionaría si agregaramos !global flag al


configurar la variable
▶ Por lo tanto podemos hacer lo siguiente:
header {
$header-color: orange !global;
color: $header-color;
}
article {
color: $header-color;
}
▶ Este código se compilará al siguiente CSS:
header {
color: orange;
}
article {
color: orange;
}

562/697
Valores de variables
▶ Una variable puede contener cualquier valor CSS que queramos
▶ Podríamos crear una variable para contener familias de fuentes, peso de la fuente,
anchos de borde, imágenes de fondo, etc.
▶ Aquí tenemos un ejemplo de algunas variables más agregadas al archivo Sass
$primary-color: orange;
$secondary-color: gold;
$font-stack: 'Open Sans', Helvetica, Sans-Serif;
$border-thick: 10px;
$border-bright: orange;
$border-style: solid;
$article-width: 60%;
$article-padding: 20px;
$article-margin: auto;

body {
color: $primary-color;
background: $secondary-color;
font-family: $font-stack;
}
article {
border: $border-thick $border-style $border-bright;
width: $article-width;
padding: $article-padding;
margin: $article-margin;
}

563/697
Valores de variables cont.

▶ Esto dará como resultado el siguiente archivo CSS:


body {
color: orange;
background: gold;
font-family: "Open Sans", Helvetica, Sans-Serif;
}

article {
border: 10px solid orange;
width: 60%;
padding: 20px;
margin: auto;
}

564/697
Valores por defecto

▶ Puede asignar un valor predeterminado a una variable, que solo se utilizará si la


variable no tiene un valor
▶ Para hacer esto, agregamos el indicador !default al final de la regla:
$primary-color: orange;
$primary-color: gold !default;

body {
color: $primary-color;
}
▶ En este caso particular, el CSS compilado será el siguiente:
body {
color: orange;
}

565/697
Valores por defecto cont.

▶ El segundo color (predeterminado) no se usó en este caso, porque ya se había


asignado un valor a esa variable
▶ Pero si elimináramos la primera línea, se usaría el segundo valor (predeterminado)
▶ Entonces, si nuestro archivo SCSS se ve así:
$primary-color: gold !default;

body {
color: $primary-color;
}
▶ El CSS compilado se verá así:
body {
color: gold;
}

566/697
Sass

Mixins

567/697
Introducción

▶ En los últimos años, HTML ha dado grandes pasos para volverse más semántico
▶ Las etiquetas refuerzan el significado del contenido en lugar de su diseño
▶ Desafortunadamente, no ocurre lo mismo con CSS
▶ Definir clases como .float-left, .row y .col es mejor que volver a definir las
propiedades flotantes para cada etiqueta HTML
▶ Hay frameworks CSS que intentan abordar el problema (la interfaz de usuario
semántica es un ejemplo popular; lo encontrará en semantic-ui.com)
▶ Sass proporciona otra forma, a través de la directiva @mixin
▶ La sintaxis es la siguiente:
@mixin <name>
{
<contents>
}

568/697
Introducción cont.

▶ Una vez que hayamos creado el mixin, simplemente usamos @include desde
donde queramos incluir las reglas
▶ Sintaxis:
<selector>
{
@include <mixin-name>

[<otras reglas>]

569/697
Introducción cont.

▶ Veamos un ejemplo sencillo


@mixin float-left {
float: left;
}

.call-out {
@include float-left;
background-color: gray;
}
▶ El CSS resultante será:
.call-out {
float: left;
background-color: gray;
}

570/697
Introducción cont.

▶ El mixin del ejemplo anterior se define en el mismo archivo donde se usa, pero
puede (y generalmente lo hará) definir mixins en un archivo aparte
▶ Simplemente agregue @import del archivo antes de usar la directiva @include
▶ Un mixin de Sass no se limita a definir reglas de propiedad; también puede incluir
selectores, incluidos los selectores principales
▶ Usando esta técnica podría definir todas las reglas para un enlace similar a un
botón en un solo mixin

571/697
Introducción cont.

@mixin a-button {
a {
background-color: blue;
color: white;
radius: 3px;
margin: 2px;

&:hover {
color: red;
}

&:visited {
color: green;
}
}
}

572/697
Introducción cont.
▶ Use la directiva @include para incluir este mixin en un estilo, como se muestra a
continuación:
@import 'a-button'; // asumiendo que a-button.scss es el nombre del archivo del mixin

.menu-button {
@include a-button;
}
▶ y la salida seria:
.menu-button a {
background-color: blue;
color: white;
radius: 3px;
margin: 2px;
}
.menu-button a:hover {
color: red;
}
.menu-button a:visited {
color: green;
}
573/697
Variables Mixin

▶ Si tiene más de una clase que incluye esta funcionalidad, está claro que el ejemplo
anterior ahorrará mucho tipeo y será más fácil de mantener
▶ Pero, ¿qué sucede si tiene varias clases que tienen la misma funcionalidad básica,
pero necesita pasar diferentes colores? Sass lo hace fácil: simplemente pase los
colores como variables, que se definen como parámetros de función

574/697
Variables Mixin

@mixin a-button($base, $hover, $link) {


a {
background-color: $base;
color: white;
radius: 3px;
margin: 2px;

&:hover {
color: $hover;
}

&:visited {
color: $link;
}
}
}

575/697
Variables Mixin

▶ Pasas los argumentos variables al mixin usando la sintaxis normal:


.menu-button {
@include a-button(blue, red, green);
}
.text-button {
@include a-button(yellow, black, grey);
}

576/697
Variables Mixin
▶ Ese ejemplo daría como resultado el siguiente CSS:
.menu-button a {
background-color: blue;
color: white;
radius: 3px;
margin: 2px;
}
.menu-button a:hover {
color: red;
}
.menu-button a:visited {
color: green;
}
.text-button a {
background-color: yellow;
color: white;
radius: 3px;
margin: 2px;
}
.text-button a:hover {
color: black;
}
.text-button a:visited { 577/697
Variables Mixin

▶ Sass incluso le permite proporcionar valores predeterminados para las variables


mixin:
@mixin a-button($base: red, $hover: green, $link: blue) {
a {
background-color: $base;
color: white;
radius: 3px;
margin: 2px;

&:hover {
color: $hover;
}

&:visited {
color: $link;
}
}
}

578/697
Variables Mixin cont.

▶ Cuando define una variable predeterminada de esta manera, solo necesita


proporcionar valores que cambian cuando incluye el mixin:
.menu-button {
@include a-button($link: orange);
}

579/697
Variables Mixin

▶ Esto daría como resultado el siguiente CSS:


.menu-button a {
background-color: blue;
color: white;
radius: 3px;
margin: 2px;
}
.menu-button a:hover {
color: red;
}
.menu-button a:visited {
color: orange;
}
▶ Como puede ver, a la regla a:visited se le asigna el color:orange, como se
proporciona, pero las otras dos reglas tienen los valores predeterminados

580/697
Variables Mixin

▶ Al igual que cuando llama a una función de Sass, solo necesita proporcionar el
nombre del parámetro si no está incluyendo los argumentos fuera de orden o
omitiendo algunos
▶ Esto funcionaría bien (aunque el botón resultante sería bastante feo):
.menu-button {
@include a-button(darkmagenta, darkolivegreen, skyblue);
}

581/697
Variables Variables
▶ Algunas propiedades CSS pueden tomar diferentes números de variables
▶ Un ejemplo es la propiedad margin, que puede tomar de 1 a 4 valores
▶ Sass admite esto usando argumentos variables, que se declaran con puntos
suspensivos después de sus nombres:
@mixin margin-mix($margin...) {
margin: $margin;
}
▶ Dada esta definición de mixin, cualquiera de las siguientes directivas @include se
transpilará sin errores:
.narrow-border {
@include margin-mix(1px);
}

.top-bottom-border {
@include margin-mix(3px 2px);
}

.varied-border {
@include margin-mix(1px 3px 6px 10px);
}
582/697
Pasar contenido a mixins
▶ En la mayoría de los casos, usará mixins para fragmentos estándar de estilo que
usará en varios lugares y se expandirá con reglas adicionales cuando las incluya
▶ Podemos crear mixins que funcionen al revés pasando un bloque de reglas al mixin
▶ No necesita una variable para hacer esto; el contenido que pase estará disponible
para el mixin a través de la directiva @content:
@mixin has-content {
html {
@content;
}
}

@include has-content {
#logo {
background-image: url(logo.svg);
}
}
▶ Esto dará como resultado la siguiente salida CSS:
html #logo {
background-image: url(logo.svg);
}
583/697
Pasar contenido a mixins

▶ Observe que la sintaxis aquí usa llaves, no paréntesis, para distinguir el contenido
de cualquier variable que el mixin pueda declarar
▶ Podemos usar ambos;
@mixin test-content($color) {
.test {
color: $color;
@content;
}
}

@include test-content(blue) {
background-color: red;
}
▶ lo que dará como resultado el siguiente CSS:
.test {
color: blue;
background-color: red;
}

584/697
Laboratorio práctico - Sass Labs

Es momento de practicar estilos


▶ Selectores
▶ Variables
▶ Mixins

585/697
Frameworks de UI

Frameworks de UI
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

586/697
Frameworks de UI

Frameworks

587/697
Angular

▶ Angular fue desarrollado en 2009 por Google


▶ La primera versión fue Angular.js
▶ Angular se conoce actualmente como un marco de JavaScript
▶ Todos los proyectos importantes de Google se han desarrollado con Angular.
▶ Angular.js es un marco MVC
▶ Una gran desventaja de Angular es que utiliza un DOM regular y, por lo tanto, se
actualiza toda la estructura de árbol de las etiquetas HTML, lo que afecta
enormemente el tiempo de carga
▶ Angular.js tiene su marco Ionic para aplicaciones móviles

588/697
Ventajas

▶ Permite arquitectura MVC


▶ Buena mantenibilidad
▶ Las aplicaciones web creadas con Angular funcionan muy bien
▶ Los proyectos ahora pueden desarrollarse, expandirse y generarse más rápidamente
gracias a tecnologías como la herramienta de línea de comandos Angular-CLI
▶ Angular proporciona un marco básico para desarrollar aplicaciones web y las
administra sin bibliotecas adicionales
▶ Sencillas pruebas unitarias y de extremo a extremo

589/697
Desventajas

▶ Vuelve a cargar la estructura de árbol de etiquetas HTML completa.


▶ Tiempo de carga lento debido a la aplicación Ionic.
▶ Debido al marco dado, Angular es relativamente rígido e inflexible.
▶ Para trabajar con Angular.js, necesitas un cierto período de entrenamiento.
▶ Si un usuario ha desactivado JavaScript en el navegador, no es posible utilizar un
SPA basado en JavaScript. Además, no siempre es compatible con navegadores
obsoletos o desconocidos.

590/697
React

▶ Facebook lanzó React.js en marzo de 2013 como una biblioteca de JavaScript.


Debido a que React solo proporciona una vista, no es apropiado para construir
una arquitectura MVC: debe resolver el modelo y el controlador usted mismo.
Además de esto, solo hay ventajas y muchas ventajas.
▶ Uno de los más grandes es que React.js usa un DOM virtual que solo compara las
diferencias de código HTML anteriores y solo carga las diferentes partes. Esto
afecta significativamente los tiempos de carga. De una manera positiva, por
supuesto.
▶ Con React.js, maneja el marcado y la lógica en el mismo archivo, lo que significa
que puede generar variables en un componente de vista (JSX). React ofrece un
tipo de soluciones móviles para aplicaciones llamadas React-Native.

591/697
Ventajas

▶ Carga rápida de nuevos datos


▶ Un archivo contiene marcado y lógica (JSX)
▶ Permite la separación de datos y presentación
▶ Es fácil de empezar y no requiere mucha práctica
▶ Como biblioteca, no tiene tantos ajustes preestablecidos, por lo que es fácil de
aprender
▶ Funcionamiento fluido de la aplicación, incluso con operaciones subyacentes
complejas o consultas a la base de datos

592/697
Desventajas

▶ Es solo una biblioteca de JavaScript, no un marco


▶ No hay posibilidad de implementar la arquitectura MVC
▶ Con frecuencia es insuficiente para desarrollar una aplicación web y requiere el uso
de otras bibliotecas.
▶ Solo vale la pena usarlo si las aplicaciones web necesitan ser altamente
interactivas.

593/697
Vue

▶ Vue.js es un marco progresivo basado en JavaScript para crear aplicaciones de una


sola página. Fue creado teniendo en cuenta la escalabilidad y la incrementalidad,
así como la facilidad de integración con otros marcos de capa de vista.
▶ Vue está construido de abajo hacia arriba para ser progresivamente adaptable, a
diferencia de otros marcos monolíticos. La biblioteca principal se enfoca
únicamente en la capa de vista, y es fácil de usar y conectar con otras bibliotecas
o aplicaciones. El ángulo de aprendizaje rápido de este marco es casi una marca
registrada. Es un marco flexible que puede usarse como una biblioteca o un marco
completo para desarrollar aplicaciones web grandes.
▶ Vue.js combina los principios útiles de los frameworks Angular y React y los
presenta en un estilo moderno y minimalista. Los desarrolladores web usan Vue.js
para crear interfaces de usuario frontend para aplicaciones móviles híbridas y
basadas en la web.

594/697
Ventajas

▶ Una lista de herramientas y bibliotecas (CLI oficial de Vue.js, Herramientas de


desarrollo, Vue Loader, Vue Router).
▶ Flexibilidad y sencillez en la utilización.
▶ Documentación completa.
▶ Reutilizable en términos de agregar numerosos componentes reactivos al código
existente.
▶ La posibilidad de la Arquitectura Basada en Componentes (CBA)

595/697
Deventajas

▶ Comunidad limitada en comparación con Angular y React


▶ El número de complementos disponibles.
▶ Desventaja del idioma porque una gran cantidad de usuarios no hablan inglés
▶ Complicaciones excesivas con flexibilidad

596/697
Frameworks de UI

Diferencias claves entre Angular, React y Vue

597/697
Architectura

▶ Hablando de arquitectura, Angular es un marco MVC completo que le brinda


todas las posibilidades para la programación lista para usar:
▶ Plantillas basadas en HTML;
▶ Inyección de dependencia;
▶ Solicitudes de Ajax;
▶ Enrutamiento;
▶ Encapsulación de componentes CSS;
▶ Utilidades de prueba de componentes;
▶ Oportunidades para crear formularios, etc.

598/697
Architectura cont.

▶ React.js, por otro lado, es una biblioteca que solo ofrece la vista, dejando que el
desarrollador decida cómo construir el modelo y el controlador. Se proporcionan
las siguientes características:
▶ Como complemento de JavaScript, se utiliza el lenguaje JSX, que es similar a XML,
en lugar de plantillas;
▶ Sin introducción de dependencias;
▶ Solicitudes de Ajax;

599/697
Architectura cont.

▶ Vue.js es una biblioteca que le permite crear interfaces web interactivas. Vue.js se
ocupa principalmente de la capa ViewModel de la arquitectura MVVM. Utiliza
enlaces de datos bidireccionales para adjuntar la vista y el modelo. Las directivas
y los filtros abstraen las operaciones DOM reales y el formato de salida.

600/697
Enlace de datos

▶ Angular.js usa el enlace bidireccional. Primero se cambia el estado del modelo y


luego se refleja la modificación del elemento de la interfaz. El elemento de la
interfaz cambia a medida que cambia el estado del modelo, razón por la cual se
utiliza el enlace de datos bidireccional.
▶ React.js tiene enlace unidireccional. Primero, se actualiza el estado del modelo y
luego refleja el cambio del elemento de la interfaz. Si cambia el elemento de la
interfaz, el estado del modelo permanece igual.
▶ Al igual que en Angular, el enlace de datos en Vue.js es bidireccional. Vue.js
sincroniza mecánicamente todo el modelo con el DOM. Esto implica que todas las
plantillas de Vue.js son fundamentalmente HTML analizable legal con algunas
características adicionales. Recuerde esto porque las plantillas de Vue son
fundamentalmente diferentes de las plantillas basadas en cadenas.

601/697
Soluciones móviles

▶ Cada uno de los tres marcos de desarrollo web comparados ofrece soluciones
móviles para el desarrollo de aplicaciones.
▶ Cuando se trata de Angular, este es el marco Ionic, que utiliza el contenedor
Cordova de Angular. Usted descarga la aplicación, que es una aplicación web que
se ejecuta dentro de un navegador web.
▶ React.js no tiene un marco similar. React Native es una plataforma para crear
aplicaciones móviles nativas reales.
▶ Vue ha anunciado su apoyo al proyecto Weex de Alibaba Group, que es un marco
de interfaz de usuario multiplataforma. Weex le permite desarrollar componentes
de navegador, así como aplicaciones de iOS y Android utilizando la misma sintaxis
de Vue.

602/697
Facilidad de aprendizaje

▶ En el caso de React.js, primero debe aprender JSX, lo cual no es un problema ya


que es bastante simple. Luego, debe pasar por la biblioteca de enrutamiento
(react-router v4, por ejemplo) y luego las bibliotecas de administración de estado
(Redux o MobX).
▶ En el caso de Angular, hay muchos más pasos que hacer e información que
aprender. A partir de términos básicos (directivas, módulos, decoradores,
componentes, servicios, entradas de dependencia, canalizaciones y plantillas),
siguen temas como detección de cambios, zonas, compilación AoT y Rx.js.
▶ Y en el caso de Vue.js, las características fundamentales pueden implementarse en
las primeras aplicaciones web en el menor tiempo posible. Vue es más simple de
entender que Angular o React ya que es más adaptable. Además, la funcionalidad
de Vue, como el uso de componentes, se superpone con la de Angular y React. La
simplicidad y adaptabilidad de Vue.js, por otro lado, tiene un inconveniente:
permite código pobre que es difícil de depurar y probar.
603/697
Sintaxis

▶ Angular está escrito en TypeScript, lo que significa que necesita algo de tiempo
para aprender a trabajar con este marco.
▶ React usa JSX y los desarrolladores nativos de Javascript están familiarizados con
él. El período de entrenamiento es más fácil y no requiere tanta preparación.
▶ Vue.js utiliza una sintaxis de plantilla basada en HTML que le permite vincular el
DOM mostrado a los datos de la instancia del elemento base de forma declarativa.
Todas las plantillas de Vue.js son HTML válido que pueden leer los analizadores
de HTML y los navegadores que siguen el estándar.

604/697
Integración

▶ Angular proporciona un marco básico para crear aplicaciones web y no requiere


bibliotecas adicionales. Es relativamente rígido e inflexible como marco completo.
▶ React.js generalmente no es suficiente para construir una aplicación web. En la
mayoría de los casos, se recomienda utilizar bibliotecas adicionales. Como
resultado, es más adaptable y fácil de integrar en las aplicaciones móviles actuales.
▶ Vue.js permite implementar características distintas de una aplicación sin alterar
la arquitectura. Cuando se trata de integrarse con otras bibliotecas, Vue es una
solución perfecta. Vue.js se puede usar para crear aplicaciones de una sola página
e interfaces en línea más complejas para aplicaciones.

605/697
Performance

▶ Para capturar todos los cambios en el DOM, Angular.js crea un observador para
cada enlace. Cada vez que se actualiza la vista, los nuevos valores se comparan
con los antiguos. Esto puede terminar en un rendimiento más bajo en aplicaciones
móviles grandes.
▶ Debido a que React usa un DOM virtual, cuando se modifica la vista, el nuevo
DOM lo compara con el DOM virtual y cambia en consecuencia.
▶ Vue.js tiene un mejor rendimiento gracias al DOM virtual, que es útil para
programas complicados. Puede ser tan pequeño como 20 KB mientras mantiene
su velocidad y versatilidad, lo que le permite lograr un rendimiento
considerablemente mejor que los marcos de la competencia.

606/697
Ecosistema

▶ Lo mejor de los marcos de trabajo de código abierto es que brindan a los


desarrolladores numerosas herramientas o bibliotecas. Gracias a la comunidad
activa, hay una gran cantidad de extensiones para Angular, React y Vue que se
pueden usar:
▶ Para facilitar el arranque de un proyecto;
▶ Para el desarrollo de aplicaciones;
▶ Por cuestiones de diseño;
▶ Para la administración de los estados.

607/697
¿Cuál es mejor?

▶ Angular.js ofrece una estructura muy clara y muchas características. Permite que
los equipos de desarrollo pasen rápidamente a la implementación sin necesidad de
definir estructuras o buscar bibliotecas adicionales. Sin embargo, a menudo está
demasiado sobrecargado para proyectos pequeños y trae un lastre innecesario.
▶ React se recomienda para proyectos con resultados de front-end pesados. Dado
que no existen estructuras claras, la estrecha cooperación entre el equipo de
desarrollo es vital. React tiene un soporte de renderizado del lado del servidor más
sólido, lo que hace que la biblioteca sea más compatible con SEO.
▶ Vue se puede utilizar para una amplia gama de aplicaciones. Puede brindar una
gran solución para prácticamente todos los tipos de proyectos debido a su
interoperabilidad con otros marcos de JavaScript y su capacidad para agregar una
lógica más complicada a los programas actuales.

608/697
¿Como escoger?

▶ Angular es una caja de herramientas completa que le ofrece todo, desde desarrollo
hasta pruebas, mientras crea una aplicación web. React es una biblioteca versátil
que se basa en la ayuda de otras bibliotecas para desarrollarse. Vue.js es un marco
revolucionario para crear interfaces de usuario y aplicaciones de una sola página,
así como una curva de aprendizaje rápida.

609/697
¿Como escoger? cont.

▶ Elige Angular si quieres:


▶ Desarrollar una aplicación grande y multifuncional.
▶ Marco confiable y escalable.
▶ Aplicaciones, chats o mensajeros en tiempo real.
▶ Iniciativas de inversión significativas y de largo plazo en aplicaciones nativas o
aplicaciones web.

610/697
¿Como escoger? cont.

▶ Elige React si quieres:


▶ Aplicaciones modernas ligeras en poco tiempo.
▶ Soluciones móviles seguras para el desarrollo web.
▶ Para desarrollar aplicaciones móviles multiplataforma o de una sola página.
▶ Para agregar nuevas características a un programa existente.

611/697
¿Como escoger? cont.

▶ Decídete por Vue.js si quieres:


▶ Aplicaciones de una sola página.
▶ Las aplicaciones dinámicas y de alto rendimiento se habilitan gracias al DOM virtual.
▶ Framework fácil de usar, para un desarrollo de aplicaciones simplificado.

612/697
Resumen
▶ No hay documentación definitiva y actualizada para React. Es de código abierto y
aparecen nuevas bibliotecas casi todos los días. Para los desarrolladores
experimentados, esta es una gran ventaja, pero puede resultar confuso para los
principiantes.
▶ Es más fácil encontrar la información que necesita usando Angular. El producto
viene con documentación detallada y pautas adicionales. Siempre puede consultar
con los miembros de la comunidad en cualquier plataforma popular si todavía
tiene alguna pregunta.
▶ Vue.js ofrece una de las mejores documentaciones. Su arquitectura basada en
componentes fue influenciada en gran medida por ReactJS. Dado que Vue es un
marco modernizado, ofrece soluciones adoptadas para el desarrollo, pero su
novedad se refleja en la falta de comunidad y otros límites.
▶ Al elegir Vue vs React vs Angular, concéntrese en el tipo de proyecto. Todos los
enfoques tienen sus pros y sus contras, ambos evolucionan y mejoran
continuamente.
613/697
Informacion adicional

▶ https://incora.software/insights/why-to-choose-angular-for-your-
development/16
▶ https://incora.software/insights/why-should-you-use-react/15

614/697
React

React
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

615/697
React

Introducción

616/697
Introducción

▶ React es una biblioteca pequeña que no viene por defecto con todo lo que
podríamos necesitar para construir una aplicación
▶ En React, escribimos código simialr a HTML directamente en el código JavaScript
▶ Un efecto secundario de trabajar con React es que promueve el uso de patrones
que son legibles, reutilizables y comprobables

617/697
Introducción cont.

▶ En enero de 2015, Netflix anunció que estaban usando React para impulsar el
desarrollo de su interfaz de usuario
▶ Más tarde ese mes, se lanzó React Native, una biblioteca para crear aplicaciones
móviles usando React
▶ Facebook también lanzó ReactVR, otra herramienta que llevó a React a una gama
más amplia de objetivos de representación
▶ En 2015 y 2016, apareció una gran cantidad de herramientas populares como
React Router y Redux para manejar tareas como el enrutamiento y la
administración de estado
▶ Después de todo, React fue catalogado como una biblioteca: preocupada por
implementar un conjunto específico de funciones, no por proporcionar una
herramienta para cada caso de uso

618/697
Introducción cont.

▶ React Fiber en 2017. Fiber fue una reescritura del algoritmo de renderizado de
React. Se reescribieron todas de las partes internas de React sin modificar la API
pública
▶ Más recientemente, en 2019, vimos el lanzamiento de Hooks, una nueva forma de
agregar y compartir lógica con estado entre componentes
▶ Blog oficial de React (https://facebook.github.io/react/blog)

619/697
React

Aplicacion Web React

620/697
Hola Mundo

▶ Las aplicaciones React se incluyen en un archivo Javascript que utilizara el DOM


para escribir sobre un elemento:
▶ En este caso el elemento HTML con id reactapp se lo llama nodo raíz
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<div id="reactapp"></div>
<script src="reactApp.bundle.js"></script>
</body>
</html>

621/697
Hola Mundo cont.
▶ El ejemplo de Hello world con React utilizando CDN es tan simple como:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<!-- Script tags including React -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js">
</script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js">
</script>
<script src="https://npmcdn.com/[email protected]/browser.min.js">
</script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
ReactDOM.render(<h1>Hello world</h1>, document.querySelector('#app'));
</script>
</body>
</html>
622/697
Hola Mundo cont.

▶ Los elementos de React son inmutables


▶ Una vez que creamos un elemento, no podemos cambiar sus hijos o atributos
▶ Un elemento es como un fotograma solitario en una película: este representa la
interfaz de usuario en cierto punto en el tiempo
import React from 'react';
import ReactDOM from 'react-dom';

import ReactAppView from './components/ReactAppView';

let viewTree = React.createElement(ReactAppView, null);


let where = document.getElementById('reactapp');

ReactDOM.render(viewTree, where);

623/697
Hola Mundo cont.

import React from 'react';

class ReactAppView extends React.Component {


constructor(props) {
super(props);
// ...
}
render() {
// ...
}
};
export default ReactAppView;

624/697
Hola Mundo cont.

render() {
let label = React.createElement('label', null,'Name: ');
let input = React.createElement('input', {
type: 'text', value: this.state.yourName,
onChange: (event) => this.handleChange(event) });
let h1 = React.createElement('h1', null, 'Hello ',
this.state.yourName, '!');
return React.createElement('div', null, label, input, h1);
}

625/697
Hola Mundo cont.

render() {
return React.createElement('div', null,
React.createElement('label', null,'Name: '),
React.createElement('input',
{ type: 'text', value: this.state.yourName,
onChange: (event) => this.handleChange(event) }),
React.createElement('h1', null,
'Hello ', this.state.yourName, '!')
);
}

626/697
Virtual DOM

▶ React no opera directamente en el modelo de objeto de documento (DOM) del


navegador, sino en un DOM virtual
▶ Una vez que se ha actualizado el DOM virtual, React determina de forma
inteligente qué cambios hacer en el DOM real
▶ El DOM virtual de React
(https://facebook.github.io/react/docs/dom-differences.html) existe
completamente en la memoria y es una representación del DOM del navegador
web
▶ Debido a esto, cuando escribimos un componente React, no estamos escribiendo
directamente en el DOM, sino que estamos escribiendo un componente virtual que
React convertirá en el DOM

627/697
React

Herramientas de desarrollo de React

628/697
Plugins del navegador

▶ Es recomendable instalar React Developer Tools para facilitar el trabajo en


proyectos de React
▶ Estas herramientas están disponibles como una extensión de navegador para
Chrome y Firefox y como una aplicación independiente para usar con Safari, IE y
React Native
▶ Una vez que instale las herramientas de desarrollo, podrá inspeccionar el árbol de
componentes de React, ver accesorios y detalles de estado, e incluso ver qué sitios
están usando React actualmente en producción
▶ https://addons.mozilla.org/en-US/firefox/addon/react-devtools/

629/697
Plugins del navegador cont.

▶ Una vez instalado, podrá ver qué sitios están usando React
▶ Cada vez que el icono de React se ilumine en la barra de herramientas del
navegador, sabrá que el sitio tiene React en la página
▶ Luego, cuando abra las herramientas para desarrolladores, habrá una nueva
pestaña visible llamada React
▶ Al hacer clic en dicha opción, se mostrarán todos los componentes que componen
la página que está viendo actualmente

630/697
React

Introducción a JSX

631/697
JSX

▶ El siguiente código, puede parecer raro, no es ni HTML, ni un string, es JSX:

const element = () => <h1>Hola Mundo!</h1>;


▶ Básicamente es una extensión de la sintáxis de JavaScript y la manera más
cómoda de desarrollar en React
▶ No es obligatorio, pero podríamos decir que todo el mundo que hace uso de la
biblioteca ReactJS, utiliza JSX
▶ La idea de meter el HTML dentro de JavaScript es muy criticada, pero se basa en
el concepto de que la lógica de la interfaz de usuario esta intrínsecamente unida a
la lógica de renderizado
▶ De esta forma, tenemos un componente que contiene en un solo archivo
JavaScript, el maquetado y la lógica

632/697
Diferencias en cuanto al HTML clásico

▶ Hay algunos atributos de las etiquetas HTML que cambian:


▶ El atributo class: En React pasa a definirse como className
▶ Los gestores de eventos como onclick: en React hay que escribirlos camelCased,
sería algo así: onClick
▶ A los atributos de un elemento HTML se les puede pasar funciones, objetos, texto,
expresiones…

633/697
Renderizando variables en JSX

▶ En el siguiente ejemplo tenemos una variable llamada name, la cual usaremos


dentro de JSX envolviéndola entre llaves:
const name = "Miraclelab";
const element = () => <h1>Hola {name}!</h1>;
▶ No solo se pueden renderizar variables, sino todo tipo de expresiones dentro de las
llaves:
▶ Funciones:
const getName = user => user.name;
const element = () => <h1>Hola {getName()}!</h1>;
▶ Operadores ternarios:
const age = 18;
const element = () => <h1>Hola {age > 18 ? "adulto" : "joven"}!</h1>;

634/697
Renderizando variables en JSX cont.

▶ Babel compila el JSX a una función de React llamada createElement()


const element = () => <h1>Hola Mundo!</h1>;
▶ Sería igual a esto:
const element = React.createElement("h1", null, "Hola Mundo!");
▶ Puedes comprobarlo visitando este https://babeljs.io/repl

635/697
Ataques de inyección

▶ Es seguro insertar datos ingresados por el usuario en JSX:


const title = response.potentiallyMaliciousInput;
// Esto es seguro:
const element = <h1>{title}</h1>;
▶ Por defecto, React DOM escapa cualquier valor insertado en JSX antes de
renderizarlo
▶ Todo es convertido en una cadena antes de ser renderizado
▶ Esto ayuda a prevenir vulnerabilidades XSS (cross-site-scripting)

636/697
Material adicional

▶ El por qué de JSX en profundidad


(https://www.youtube.com/watch?v=x7cQ3mrcKaY)

637/697
React

Renderizando elementos

638/697
Renderizando elementos

▶ Ahora que hemos visto como funciona JSX es hora de mancharnos las manos y
renderizar nuestros propios componentes
▶ Para ello nos vamos a ayudar con bibiloteca create-react-app que deberíamos
tener instalada
▶ create-react-app nos ayuda a iniciar un proyecto en React dándonos un
pequeño boilerplate y configurandonos nuestro proyecto para que, en principio, no
tengamos que preocuparnos de configuraciones
▶ Para iniciar un proyecto con create-react-app es tan fácil como seguir los
siguientes pasos:
create-react-app render-components
cd render-components
npm start

639/697
Renderizando elementos cont.

▶ Esto nos creará una estructura como esta:

640/697
Renderizando elementos cont.

▶ App es el componente principal de la aplicación y se usa en el index.js:


ReactDOM.render(<App />, document.getElementById('root'));
▶ Esta etiqueta esta en el archivo index.js dentro de la carpeta public:
<div id="root"></div>

641/697
React

Componentes y propiedades

642/697
Componentes y Propiedades

▶ Los componentes permiten separar la interfaz de usuario en piezas independientes,


reutilizables y pensar en cada pieza de forma aislada
▶ Conceptualmente, los componentes son como las funciones de JavaScript
▶ Aceptan entradas arbitrarias (llamadas ”props”) y devuelven elementos React que
describen lo que debe aparecer en la pantalla

643/697
Componente funcionales

▶ La forma más sencilla de definir un componente es escribir una función de


JavaScript:
const Welcome = props => <h1>Hola, {props.name}</h1>;
▶ Esta función es un componente de React válido que acepta un solo argumento de
objeto ”props” (que proviene de propiedades) con datos y devuelve un elemento
de React
▶ Llamamos a dichos componentes ”funcionales” porque literalmente son funciones
JavaScript

644/697
Componentes de clase

▶ También podemos utilizar una clase de ES6 para definir un componente:


class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

645/697
Restricciones

▶ Las props son de solo lectura


▶ Ya sea que declaremos un componente como una función o como una clase, este
nunca debe modificar sus props
▶ React es bastante flexible pero tiene una sola regla estricta:
▶ Todos los componentes de React deben actuar como funciones puras con respecto a
sus props

646/697
React

Estado

647/697
Estado

▶ Ahora introducimos el concepto de estado en un componente de React


const Counter = props => {
let count = 0;

let increment = () => {


count += 1;
};

return (
<>
<div>{count}</div>
<button onClick={increment}>Increment</button>
</>
);
};
▶ Para actualizar la interfaz la única manera que hay es a través del state
▶ Para poder utilizar el estado de un componente tenemos dos opciones
dependiendo de si hablamos de componentes funcionales o componentes de clase
648/697
Componentes funcionales
▶ Importamos useState un hook que viene de React (esto lo veremos más adelante)
▶ useState devuelve un arreglo donde el primer elemento es el valor mutable
▶ El segundo elemento del arreglo es el método que actualiza el primero
▶ Así quedaría el componente anterior actualizado:
import React, { useState } from "react";

const Counter = props => {


const [count, setCount] = useState(0);

let increment = () => {


setCount(count + 1);
};

return (
<>
<div>{count}</div>
<button onClick={increment}>Increment</button>
</>
);
};
649/697
Componentes de clase
▶ Para pasar cualquier componente funcional a uno de clase solo hay que seguir los
siguientes pasos:
1. Crear una clase ES6 con el mismo nombre que herede de React.Component
2. Agregar un único método vacío llamado render()
3. Mover el cuerpo de la función al método render()
4. Reemplazar props con this.props en el cuerpo de render()
5. Borrar el resto de la declaración de la función ya vacía
▶ Quedaría de la siguiente manera:
class Counter extends React.Component {
render() {
return (
<>
<div>{count}</div>
<button onClick={increment}>Increment</button>
</>
);
}
}

650/697
Componentes de clase cont.

▶ Una vez que tenemos una clase podemos usar el state


▶ Para agregar estado a una clase basta con añadirlo como propiedad a traves del
constructor:
class Counter extends React.Component {
constructor(props) {
this.state = {
count: 0
};
}

651/697
Componentes de clase cont.

▶ En lugar de utilizar count usaremos this.state.count:


class Counter extends React.Component {
cousntructor(props) {
this.state = {
count: 0
};
}

render() {
return (
<>
<div>{this.state.count}</div>
</>
);
}
}

652/697
Componentes de clase cont.
▶ El estado NUNCA se debe modificar usando this.state.count = 2
▶ Existe una función llamada this.setState que podemos pasarle un objeto que
utilizará para modificar el estado
▶ Quedaría algo asi:
class Counter extends React.Component {
cousntructor(props) {
this.state = {
count: 0
};
}

increment() {
this.setState({ count: this.state.count + 1 });
}

render() {
return (
<>
<div>{this.state.count}</div>
<button onClick={() => this.increment()}>Increment</button>
</>
653/697
Las actualizaciones del estado pueden ser asíncronas

▶ React puede agrupar varias invocaciones a setState() en una sola actualización


para mejorar el rendimiento
▶ Debido a que this.props y this.state pueden actualizarse de forma
asincrónica, no debes confiar en sus valores para calcular el siguiente estado
▶ Por ejemplo, el código anterior puede fallar en actualizar el contador
▶ Para arreglarlo, usa una segunda forma de setState() que acepta una función en
lugar de un objeto
▶ Esa función recibirá el estado previo como primer argumento, y las props en el
momento en que se aplica la actualización como segundo argumento:
this.setState(state => ({
count: state.count + 1
}));

654/697
Las actualizaciones de estado se fusionan
▶ Cuando invocamos a setState(), React combina el objeto que proporcionaste
con el estado actual
▶ Por ejemplo, tu estado puede contener varias variables independientes:
state = {
posts: [],
comments: []
};
▶ Luego puedemos actualizarlas independientemente con invocaciones separadas de
setState():
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});

fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
655/697
React

Renderizado condicional

656/697
Renderizado condicional

▶ En React, puedes crear distintos componentes que encapsulan el comportamiento


que necesitas
▶ Entonces, puedes renderizar solamente algunos de ellos, dependiendo del estado
de tu aplicación.
▶ El renderizado condicional en React funciona de la misma forma que lo hacen las
condiciones en JavaScript
▶ Usa operadores de JavaScript como if o el operador condicional para crear
elementos representando el estado actual, y deja que React actualice la interfaz de
usuario para emparejarlos
▶ Considera estos dos componentes:
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}

657/697
Renderizado condicional

function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
▶ Vamos a crear un componente Greeting que muestra cualquiera de estos
componentes dependiendo de si el usuario ha iniciado sesión:
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
<Greeting isLoggedIn={false} />,

658/697
If en una línea con operador lógico &&

▶ Puedes embeber cualquier expresión en JSX envolviéndola en llaves


▶ Esto incluye al operador lógico && de JavaScript
▶ Puede ser útil para incluir condicionalmente un elemento:
const Users = props => {
const users = props.users;

return users.length ? <UsersList /> : <EmptyList />;


};

659/697
If-Else en una línea con operador condicional

const Greeting = props => {


const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? "currently" : "not"}</b> logged in.
</div>
);
};

660/697
Evitar que el componente se renderice

▶ En casos excepcionales, es posible que desees que un componente se oculte a sí


mismo aunque haya sido renderizado por otro componente
▶ Para hacer esto, devuelve null en lugar del resultado de renderizado.
const Greeting = props => {
if (props.isLoggedIn) {
return null;
}
return <div>The user is logged in.</div>;
};

661/697
React

Hooks

662/697
Introducción

▶ Hooks son una nueva característica en React 16.8


▶ Nos permiten usar el estado y otras características de React sin escribir una clase
▶ React tiene los siguientes hooks integrados:
▶ Basicos:
▶ useState
▶ useEffect
▶ useContext
▶ Adicionales:
▶ useReducer
▶ useCallback
▶ useMemo
▶ useRef
▶ useImperative
▶ useLayoutEffect
▶ useDebugValue

663/697
useState()

▶ Sin hooks escribiríamos algo así:


class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}

664/697
useState() cont.

▶ Con hooks quedaría así:


import React, { useState } from 'react';

function Example() {
// Declaración de una variable de estado que llamaremos "count"
const [count, setCount] = useState(0);

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

665/697
Declarando múltiples variables de estado

▶ Puedes usar el Hook de estado más de una vez en un mismo componente:


function ExampleWithManyStates() {
// Declarar múltiple variables de estado!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}

666/697
useEffect()
▶ El Hook useEffect, agrega la capacidad de realizar efectos secundarios desde un
componente funcional
▶ Tiene el mismo propósito que componentDidMount, componentDidUpdate y
componentWillUnmount en componentes de clases de React, pero unificadas en
una sola API
▶ Con clases:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

componentDidMount() {
console.log(`You clicked ${this.state.count} times`);
}

componentDidUpdate() {
console.log(`You clicked ${this.state.count} times`);
} 667/697
Declarando múltiples variables de estado cont.

▶ Con hooks:
import React, { useState, useEffect } from 'react';

function Example() {
const [count, setCount] = useState(0);

useEffect(() => {
console.log(`You clicked ${count} times`);
});

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

668/697
¿Qué hace useEffect?

▶ Al usar este Hook, le estamos indicando a React que el componente tiene que
hacer algo después de renderizarse
▶ React recordará la función que le pasamos (nos referiremos a ella como el
”efecto”), y se invocará más tarde después de actualizar el DOM
▶ En este efecto, actualizamos mostramos por consola una leyenda, pero también
podríamos hacer peticiones de datos o invocar alguna API externa

669/697
¿Por qué se llama a useEffect dentro del componente?

▶ Poner useEffect dentro del componente nos permite acceder a la variable de


estado count (o a cualquier prop) directamente desde el efecto
▶ No necesitamos una API especial para acceder a ella, ya que se encuentra en el
ámbito de la función

670/697
¿Se ejecuta useEffect después de cada renderizado?

▶ ¡Sí! Por defecto se ejecuta después del primer renderizado y después de cada
actualización
▶ En vez de pensar en términos de ”montar” y ”actualizar”, puede resultar más fácil
pensar en los efectos que ocurren ”después del renderizado”
▶ React se asegura de que el DOM se ha actualizado antes de llevar a cabo el efecto

671/697
Como conseguir el mismo funcionamiento que los ciclos de vida

▶ componentDidMount()
class Example extends React.Component {
componentDidMount() {
console.log('I am mounted!');
}
render() {
return null;
}
}
function Example() {
useEffect(() => console.log('mounted'), []);
return null;
}

672/697
Como conseguir el mismo funcionamiento que los ciclos de vida

▶ componentDidUpdate()
componentDidUpdate() {
console.log('mounted or updated');
}
useEffect(() => console.log('mounted or updated'));

673/697
Como conseguir el mismo funcionamiento que los ciclos de vida

▶ componentWillUnmount()
componentWillUnmount() {
console.log('will unmount');
}
useEffect(() => {
return () => {
console.log('will unmount');
}
}, []);

674/697
Construyendo Hooks personalizados

▶ Construir Hooks personalizados permite extraer la lógica del componente en


funciones reutilizables
function useCallAPI(url) {
const [data, setData] = useState([]);

const getData = async (url) => {


let response = await fetch(url);
let data = await response.json();
setData(data.results);
}

useEffect(() => {
getData(url);
}, []);

return data;
}

675/697
Construyendo Hooks personalizados

▶ Luego lo podemos usar así:


function App() {

const data = useCallAPI('http://www.mocky.io/v2/5d965a7233000003cd2f9091');

return (
<>
<RedditPosts data={data} />
</>
);
}

676/697
React

Context

677/697
Introduccion

▶ Context provee una forma de pasar datos a través del árbol de componentes sin
tener que pasar props manualmente en cada nivel
▶ En una aplicación típica de React, los datos se pasan de arriba hacia abajo (de
padre a hijo) a través de props, pero esto puede ser complicado para ciertos tipos
de props (por ejemplo, localización del tema de la interfaz gráfica) que son
necesarios para muchos componentes dentro de una aplicación
▶ Context proporciona una forma de compartir valores entre componentes sin tener
que pasar explícitamente un prop a través de cada nivel del árbol

678/697
Cuándo usar Context

▶ Context está diseñado para compartir datos que pueden considerarse globales
para un árbol de componentes en React, como el usuario autenticado
actualmente, el tema o el idioma preferido
▶ Por ejemplo, en el código a continuación, pasamos manualmente un prop de
tema para darle estilo al componente Button:

679/697
Cuándo usar Context cont.

class App extends React.Component {


render() {
return <Toolbar theme="dark" />;
}
}

function Toolbar(props) {
// El componente Toolbar debe tener un prop adicional "theme"
// y pasarlo a ThemedButton. Esto puede llegar a ser trabajoso
// si cada botón en la aplicación necesita saber el tema,
// porque tendría que pasar a través de todos los componentes
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}

class ThemedButton extends React.Component {


render() {
return <Button theme={this.props.theme} />;
}
}

680/697
Cuándo usar Context cont.

▶ Usando Context podemos evitar pasar props a través de elementos intermedios:

// Context nos permite pasar un valor a lo profundo del árbol de componentes


// sin pasarlo explícitamente a través de cada componente.
// Crear un Context para el tema actual (con "light" como valor predeterminado).
const ThemeContext = React.createContext('light');

class App extends React.Component {


render() {
// Usa un Provider para pasar el tema actual al árbol de abajo.
// Cualquier componente puede leerlo, sin importar qué tan profundo se encuentre.
// En este ejemplo, estamos pasando "dark" como valor actual.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}

681/697
Cuándo usar Context cont.

// Un componente en el medio no tiene que


// pasar el tema hacia abajo explícitamente.
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}

class ThemedButton extends React.Component {


// Asigna un contextType para leer el contexto del tema actual.
// React encontrará el Provider superior más cercano y usará su valor.
// En este ejemplo, el tema actual es "dark".
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}

682/697
API

▶ React.createContext
const MyContext = React.createContext(defaultValue);
▶ Crea un objeto Context
▶ Cuando React renderiza un componente que se suscribe a este objeto Context,
este leerá el valor de contexto actual del Provider más cercano en el árbol
▶ El argumento defaultValue es usado únicamente cuando un componente no
tiene un Provider superior a él en el árbol
▶ Esto puede ser útil para probar componentes de forma aislada sin contenerlos
▶ Nota: pasar undefined como valor al Provider no hace que los componentes
que lo consumen utilicen defaultValue

683/697
API cont.
▶ Context.Provider
<MyContext.Provider value={/* algún valor */}>
▶ Cada objeto Context viene con un componente Providers de React que permite
que los componentes que lo consumen se suscriban a los cambios del contexto
▶ Acepta un valor que se pasará a los componentes consumidores que son
descendientes de este Provider
▶ Un Provider puede estar conectado a muchos consumidores
▶ Los Providers pueden estar anidados para sobreescribir los valores más
profundos dentro del árbol
▶ Todos los consumidores que son descendientes de un Provider se vuelven a
renderizar cada vez que cambia el valor del Provider
▶ La propagación del Provider a sus consumidores descendientes no está sujeta al
método shouldComponentUpdate, por lo que el consumidor se actualiza incluso
cuando un componente padre evita la actualización
684/697
Actualizando Context desde un componente anidado

▶ A menudo es necesario actualizar el contexto desde un componente que está


anidado en algún lugar del árbol de componentes
▶ En este caso, podemos pasar una función a través del contexto para permitir a los
consumidores actualizar el contexto (theme-context.js):
// ¡Asegúrese de que la forma del valor predeterminado pasado
// a createContext coincida con la forma que esperan los consumidores!
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});

685/697
Actualizando Context desde un componente anidado cont.

▶ theme-toggler-button.js
import {ThemeContext} from './theme-context';

function ThemeTogglerButton() {
// El botón toggleTheme no solo recibe el tema, sino
// también una función de alternancia de tema del contexto
return (
<ThemeContext.Consumer>
{({theme, toggleTheme}) => (
<button
onClick={toggleTheme}
style={{backgroundColor: theme.background}}>
Toggle Theme
</button>
)}
</ThemeContext.Consumer>
);
}

export default ThemeTogglerButton;

686/697
Actualizando Context desde un componente anidado cont.

import {ThemeContext, themes} from './theme-context';


import ThemeTogglerButton from './theme-toggler-button';

class App extends React.Component {


constructor(props) {
super(props);

this.toggleTheme = () => {
this.setState(state => ({
theme:
state.theme === themes.dark
? themes.light
: themes.dark,
}));
};

// El estado también contiene la función de actualización,


// por lo que se transmitirá al proveedor de contexto.
this.state = {
theme: themes.light,
toggleTheme: this.toggleTheme,
};
}

687/697
Actualizando Context desde un componente anidado cont.

render() {
// Todo el estado se pasa al proveedor
return (
<ThemeContext.Provider value={this.state}>
<Content />
</ThemeContext.Provider>
);
}
}

function Content() {
return (
<div>
<ThemeTogglerButton />
</div>
);
}

ReactDOM.render(<App />, document.root);

688/697
Accediento con Hooks

▶ El hook useContext permite el componente actual para consumir el contexto


▶ El argumento es un objeto Contexto
▶ Debe haber sido creado por React.createContext()
▶ El valor depende del Provider mas cercano
▶ Debe estar anidado dentro de <MyContext.Provider>
function Display() {
const value = useContext(NumberContext);
return <div>The answer is {value}.</div>;
}

689/697
React

Styled-components

690/697
Instalación

▶ styled-components utiliza los template strings para dar estilos a los


componentes
▶ Esto elimina el tener que mapear los estilos a los componentes
npm install --save styled-components

691/697
Ejemplos básicos

▶ Simplemente hay que importar styled:


import styled from 'styled-components';
▶ Y después basta con usar styled seguido de una etiqueta HTML:
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: red;
`;
const Wrapper = styled.section`
padding: 4em;
background: green;
`;

692/697
Adaptando el estilo según las props

▶ Al ser un template string de ES6 podemos interpolar expresiones:


const Button = styled.button`
background: ${props => props.primary ? "red" : "white"};
color: ${props => props.primary ? "white" : "red"};

font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid red;
border-radius: 3px;
`;

693/697
Extendiendo estilos

▶ Podemos extender estilos de otros componentes


▶ La única diferencia es que en vez de usar una etiqueta usaremos dicho
componente en styled:
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;

const TomatoButton = styled(Button)`


color: tomato;
border-color: tomato;
`;

694/697
Animaciones

▶ Se pueden crear animaciones reutilizables de manera sencilla


▶ Simplemente tenemos que usar keyframes para después usarla dentro de nuestro
componente:
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
fontsize: 1.2rem;
`;

695/697
Últimas diapositivas

Últimas diapositivas
Luciano Diamand

© Copyright 2022, Luciano Diamand.


Creative Commons BY-SA 3.0 license.
Correcciones, sugerenias, contribuciones y traducciones son bienvenidas!

696/697
Última diapositiva

Gracias!
Y que el Código Fuente te acompañe

697/697

También podría gustarte