Merge pull request from EmmanuelArenas/spanish-translation

Spanish translation
pull/519/head
Asabeneh 3 years ago committed by GitHub
commit cf35af992c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,7 +14,7 @@
</div>
[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](..)
[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](../dia_18_Promesas/dia_18_Promesas.md)
![Thirty Days Of JavaScript](../images/banners/day_1_17.png)
@ -230,4 +230,4 @@ localStorage.clear();
🎉 ¡FELICITACIONES! 🎉
[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](..)
[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](../dia_18_Promesas/dia_18_Promesas.md)

@ -0,0 +1,273 @@
<div align="center">
<h1> 30 Días de JavaScript: Promesas</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Autor:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Enero, 2020</small>
</sub>
</div>
[<< Día 17](../dia_17_Web_storages/dia_17_web_storages.md) | [Día 19>>](../dia_19_Closures/dia_19_closures.md)
![Thirty Days Of JavaScript](../images/banners/day_1_18.png)
- [Día 18](#día-18)
- [Promesas](#promesas)
- [Callbacks](#callbacks)
- [Constructor de promesas](#constructor-de-promesas)
- [Fetch API](#fetch-api)
- [Async y Await](#async-y-await)
- [Ejercicios](#ejercicios)
- [Ejercicios: Nivel 1](#ejercicios-nivel-1)
- [Ejercicios: Nivel 2](#ejercicios-nivel-2)
- [Ejercicios: Nivel 3](#ejercicios-nivel-3)
# Día 18
## Promesas
Los seres humanos damos o recibimos una promesa para realizar alguna actividad en algún momento. Si cumplimos la promesa, hacemos felices a los demás, pero si no la cumplimos, puede provocar descontento. La promesa en JavaScript tiene algo en común con los ejemplos anteriores.
Una promesa es una forma de manejar operaciones asíncronas en JavaScript. Permite a los manejadores con un valor eventual de éxito o razón de fracaso de una acción asíncrona. Esto permite que los métodos asíncronos devuelvan valores como los métodos síncronos: en lugar de devolver inmediatamente el valor final, el método asíncrono devuelve una promesa de proporcionar el valor en algún momento en el futuro.
Una promesa está en uno de estos estados:
- pendiente: estado inicial, ni cumplido ni rechazado.
- cumplido: significa que la operación se ha completado con éxito.
- rechazado: significa que la operación ha fallado.
Una promesa pendiente puede ser cumplida con un valor, o rechazada con una razón (error). Cuando ocurre cualquiera de estas opciones, se llaman los manejadores asociados puestos en cola por el método _then_ de una promesa. (Si la promesa ya se ha cumplido o ha sido rechazada cuando se adjunta un manejador correspondiente, se llamará al manejador, por lo que no hay una condición de competencia entre una operación asíncrona que se completa y sus manejadores que se adjuntan).
Como los métodos _Promise.prototype.then()_ y _Promise.prototype.catch()_ devuelven promesas, pueden encadenarse.
## Callbacks
Para entender muy bien la promesa, entendamos primero la devolución de llamada. Veamos los siguientes callbacks. A partir de los siguientes bloques de código se notará, la diferencia entre callback y promesas.
- call back
Veamos una función callback que puede tomar dos parámetros. El primer parámetro es err y el segundo es result. Si el parámetro err es falso, no habrá error, de lo contrario retornará un error.
En este caso el err tiene un valor y devolverá el bloque err.
```js
//Callback
const doSomething = (callback) => {
setTimeout(() => {
const skills = ["HTML", "CSS", "JS"];
callback("It did not go well", skills);
}, 2000);
};
const callback = (err, result) => {
if (err) {
return console.log(err);
}
return console.log(result);
};
doSomething(callback);
```
```sh
// después de 2 segundos se imprimirá
It did not go well
```
En este caso el err es falso y devolverá el bloque else que es el resultado.
```js
const doSomething = (callback) => {
setTimeout(() => {
const skills = ["HTML", "CSS", "JS"];
callback(false, skills);
}, 2000);
};
doSomething((err, result) => {
if (err) {
return console.log(err);
}
return console.log(result);
});
```
```sh
// después de 2 segundos imprimirá las habilidades
["HTML", "CSS", "JS"]
```
### Constructor de promesas
Podemos crear una promesa utilizando el constructor Promise. Podemos crear una nueva promesa utilizando la palabra clave `new` seguida de la palabra `Promise` y seguida de un paréntesis. Dentro del paréntesis, toma una función `callback`. La función de callback de la promesa tiene dos parámetros que son las funciones _`resolve`_ y _`reject`_.
```js
// sintaxis
const promise = new Promise((resolve, reject) => {
resolve("success");
reject("failure");
});
```
```js
// Promesas
const doPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const skills = ["HTML", "CSS", "JS"];
if (skills.length > 0) {
resolve(skills);
} else {
reject("Something wrong has happened");
}
}, 2000);
});
doPromise
.then((result) => {
console.log(result);
})
.catch((error) => console.log(error));
```
```sh
["HTML", "CSS", "JS"]
```
La promesa anterior se ha resuelto con resolución.
Veamos otro ejemplo cuando la promesa se resuelve con el rechazo (reject).
```js
// Promesa
const doPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const skills = ["HTML", "CSS", "JS"];
if (skills.includes("Node")) {
resolve("fullstack developer");
} else {
reject("Something wrong has happened");
}
}, 2000);
});
doPromise
.then((result) => {
console.log(result);
})
.catch((error) => console.error(error));
```
```sh
Something wrong has happened
```
## Fetch API
La API Fetch proporciona una interfaz para obtener recursos (incluso a través de la red). A cualquiera que haya utilizado XMLHttpRequest le resultará familiar, pero la nueva API ofrece un conjunto de funciones más potente y flexible. En este reto utilizaremos fetch para solicitar url y APIS. Además de esto, veamos una demostración del caso de uso de las promesas en el acceso a los recursos de la red utilizando la API fetch.
```js
const url = "https://restcountries.com/v2/all"; // api de países
fetch(url)
.then((response) => response.json()) // acceder a los datos de la API como JSON
.then((data) => {
// obtener los datos
console.log(data);
})
.catch((error) => console.error(error)); // manejo de errores si ocurre algo incorrecto
```
## Async y Await
Async y await es una forma elegante de manejar las promesas. Es fácil de entender y limpio de escribir.
```js
const square = async function (n) {
return n * n;
};
square(2);
```
```sh
Promesa {<resolved>: 4}
```
La palabra _async_ delante de una función significa que esa función devolverá una promesa. La función cuadrada anterior en lugar de un valor devuelve una promesa.
¿Cómo accedemos al valor de la promesa? Para acceder al valor de la promesa, utilizaremos la palabra clave _await_.
```js
const square = async function (n) {
return n * n;
};
const value = await square(2);
console.log(value);
```
```sh
4
```
Ahora, como puedes ver en el ejemplo anterior escribiendo async delante de una función creamos una promesa y para obtener el valor de una promesa utilizamos await. Async y await van juntos, uno no puede existir sin el otro.
Vamos a obtener los datos de la API utilizando tanto el método promise como el método async y await.
- promesa
```js
const url = "https://restcountries.com/v2/all";
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => console.error(error));
```
- async y await
```js
const fetchData = async () => {
try {
const response = await fetch(url);
const countries = await response.json();
console.log(countries);
} catch (err) {
console.error(err);
}
};
console.log("===== async and await");
fetchData();
```
🌕 Eres consistente y has cumplido tu promesa, has llegado al día 18. Mantén tu promesa y resuelve el desafío con determinación. Has dado 18 pasos adelante en tu camino hacia la grandeza. Ahora haz algunos ejercicios para tu cerebro y tus músculos.
## Ejercicios
```js
const countriesAPI = "https://restcountries.com/v2/all";
const catsAPI = "https://api.thecatapi.com/v1/breeds";
```
### Ejercicios: Nivel 1
1. Lee la API de los países utilizando fetch e imprime el nombre del país, la capital, los idiomas, la población y la superficie.
### Ejercicios: Nivel 2
1. Imprime todos los nombres de los gatos en la variable catNames.
### Ejercicios: Nivel 3
1. Lee el api de los gatos y encuentra el peso medio del gato en unidad métrica.
2. Lee la api de países y descubre los 10 países más grandes
3. Lea la api de los países y cuente el número total de lenguas del mundo utilizadas como oficiales.
🎉 ¡FELICITACIONES! 🎉
[<< Día 17](../dia_17_Web_storages/dia_17_web_storages.md) | [Día 19>>](../dia_19_Closures/dia_19_closures.md)

@ -0,0 +1,105 @@
<div align="center">
<h1> 30 Días de JavaScript: Closures</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Autor:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Enero, 2020</small>
</sub>
</div>
[<< Día 18](../dia_18_Promesas/dia_18_Promesas.md) | [Día 20 >>](../dia_20_Escribiendo_Codigos_Limpios/dia_20_escribiendo_codigos_limpios.md)
![Thirty Days Of JavaScript](../images/banners/day_1_19.png)
- [Día 19](#día-19)
- [Closure](#closure)
- [Ejercicios](#exercises)
- [Ejercicios: Nivel 1](#exercises-level-1)
- [Ejercicios: Nivel 2](#exercises-level-2)
- [Ejercicios: Nivel 3](#exercises-level-3)
# Día 19
## Closure
JavaScript permite escribir una función dentro de una función externa. Podemos escribir tantas funciones internas como queramos. Si la función interna accede a las variables de la función externa entonces se llama closure (clausura).
```js
function outerFunction() {
let count = 0;
function innerFunction() {
count++;
return count;
}
return innerFunction;
}
const innerFunc = outerFunction();
console.log(innerFunc());
console.log(innerFunc());
console.log(innerFunc());
```
```sh
1
2
3
```
Veamos más ejemplos de funciones internas
```js
function outerFunction() {
let count = 0;
function plusOne() {
count++;
return count;
}
function minusOne() {
count--;
return count;
}
return {
plusOne: plusOne(),
minusOne: minusOne(),
};
}
const innerFuncs = outerFunction();
console.log(innerFuncs.plusOne);
console.log(innerFuncs.minusOne);
```
```sh
1
0
```
🌕 Estás haciendo progresos. Mantén tu ritmo, sigue con el buen trabajo. Ahora haz algunos ejercicios para tu cerebro y para tus músculos.
## Ejercicios
### Ejercicios: Nivel 1
1. Crear una closure que tenga una función interna
### Ejercicios: Nivel 2
1. Crear una closure que tenga tres funciones internas
### Ejercicios: Nivel 3
1. Crear una función de salida de personAccount. Tiene variables internas de nombre, apellido, ingresos y gastos. Tiene las funciones internas totalIncome, totalExpense, accountInfo,addIncome, addExpense y accountBalance. Los ingresos son un conjunto de ingresos y su descripción y los gastos son también un conjunto de gastos con su descripción.
🎉 ¡FELICITACIONES! 🎉
[<< Día 18](../dia_18_Promesas/dia_18_Promesas.md) | [Día 20 >>](../dia_20_Escribiendo_Codigos_Limpios/dia_20_escribiendo_codigos_limpios.md)

@ -0,0 +1,376 @@
<div align="center">
<h1> 30 Días de JavaScript: Escribiendo Códigos Limpios</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Autor:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Enero, 2020</small>
</sub>
</div>
[<< Día 19](../dia_19_Closures/dia_19_closures.md) | [Día 21 >>](..)
![Thirty Days Of JavaScript](../images/banners/day_1_20.png)
- [Día 20](#día-20)
- [Escribiendo código limpio](#escribiendo-código-limpio)
- [Guía de estilo JavaScript](#guía-de-estilo-javascript)
- [¿Por qué necesitamos una guía de estilo?](#¿por-qué-necesitamos-una-guía-de-estilo)
- [Guía de estilo JavaScript de Airbnb](#guía-de-estilo-javascript-de-airbnb)
- [Guía de estilo estándar de JavaScript](#guía-de-estilo-estándar-de-javascript)
- [Guía de estilo JavaScript de Google](#guía-de-estilo-javascript-de-google)
- [Convenciones de codificación en JavaScript](#convenciones-de-codificación-en-javascript)
- [Convenciones usadas en 30DíasDeJavaScript](#convenciones-usadas-en-30díasdejavascript)
- [Variables](#variables)
- [Arrays](#arrays)
- [Funciones](#funciones)
- [Bucles](#bucles)
- [Objetos](#objetos)
- [Condicional](#condicional)
- [Clases](#clases)
# Día 20
## Escribiendo código limpio
### Guía de estilo JavaScript
Una guía de estilo de JavaScript es un conjunto de normas que indica cómo debe escribirse y organizarse el código de JavaScript. En esta sección, hablaremos de las guías de JavaScript y de cómo escribir un código limpio.
JavaScript es un lenguaje de programación, como el lenguaje humano, tiene una sintaxis. La sintaxis de JavaScript debe escribirse siguiendo una determinada pauta de estilo para convencer y simplificar.
### ¿Por qué necesitamos una guía de estilo?
Has estado codificando solo durante mucho tiempo, pero ahora parece que trabajas en equipo. No importa de qué manera escribas tu código, siempre y cuando funcione, sin embargo, cuando trabajas en un equipo de 10, 20 o más desarrolladores en un proyecto y en la misma base de código, el código será desordenado y difícil de manejar si no hay ninguna guía a seguir.
Puede desarrollar sus propias directrices y convenciones o también puede adaptar directrices bien desarrolladas. Conozcamos las guías más comunes.
Guías de estilo de JavaScript más comunes
- Guía de estilo JavaScript de Airbnb
- Guía de estilo estándar de JavaScript
- Guía de estilo JavaScript de Google
#### Guía de estilo JavaScript de Airbnb
Airbnb tiene una de las guías de estilo JavaScript más populares de Internet. También cubre casi todos los aspectos de JavaScript y es adoptado por muchos desarrolladores y empresas. Puede consultar la [Guía de estilo de Airbnb](https://github.com/airbnb/javascript). Yo también recomendaría probarlo. Su estilo es muy fácil de usar y sencillo de entender.
#### Guía de estilo estándar de JavaScript
Esta guía no es tan popular como la de Airbnb, pero merece la pena echarle un vistazo. Han eliminado el punto y coma en su [guía de estilo](https://standardjs.com/).
#### Guía de estilo JavaScript de Google
No diré mucho sobre la guía de Google. No las he usado, más bien te sugiero que eches un vistazo desde este [link](https://google.github.io/styleguide/jsguide.html).
### Convenciones de codificación en JavaScript
En este desafío también utilizamos las convenciones y guías generales de codificación de JavaScript. Las convenciones de codificación son pautas de estilo de programación desarrolladas por un individuo, un equipo o una empresa.
Las convenciones de codificación ayudan:
- para escribir un código limpio
- para mejorar la legibilidad del código
- para mejorar la reutilización y el mantenimiento del código
Las convenciones de codificación incluyen
- Reglas de declaración y denominación de las variables
- Reglas de declaración y denominación de las funciones
- Reglas para el uso de espacios en blanco, sangría y comentarios
- Prácticas y principios de programación
#### Convenciones usadas en 30DíasDeJavaScript
En este reto seguimos la convención habitual de JavaScript pero he añadido también mi preferencia de escritura.
- Utilizamos camelCase para las variables y las funciones.
- Todos los nombres de las variables comienzan con una letra.
- Hemos optado por utilizar _const_ para las constantes, los arrays, los objetos y las funciones. En lugar de las comillas dobles, hemos optado por utilizar las comillas simples o backtick. Las comillas simples se están poniendo de moda.
- También hemos eliminado el punto y coma de nuestro código, pero es una cuestión de preferencia personal.
- Espacio alrededor de los operadores aritméticos, operadores de asignación y después de la coma
- Función de flecha en lugar de declaración de función
- Retorno explícito en lugar de implícito si la función es de una línea
- No hay coma final en el último valor de un objeto
- Preferimos este +=, -=, \*= /=, \*\*= en lugar de la versión más larga
- Cuando usamos console.log() es bueno imprimir con una cadena de etiquetas para identificar de dónde viene la consola
#### Variables
```js
let firstName = "Asabeneh";
let lastName = "Yetayeh";
let country = "Finland";
let city = "Helsinki";
const PI = Math.PI;
const gravity = 9.81;
```
#### Arrays
Hemos optado por hacer que los nombres de los arrays sean plurales
- names
- numbers
- countries
- languages
- skills
- fruits
- vegetables
```js
// arrays
const names = ["Asabeneh", "Mathias", "Elias", "Brook"];
const numbers = [0, 3.14, 9.81, 37, 98.6, 100];
const countries = ["Finland", "Denmark", "Sweden", "Norway", "Iceland"];
const languages = ["Amharic", "Arabic", "English", "French", "Spanish"];
const skills = ["HTML", "CSS", "JavaScript", "React", "Python"];
const fruits = ["banana", "orange", "mango", "lemon"];
const vegetables = ["Tomato", "Potato", "Cabbage", "Onion", "Carrot"];
```
#### Funciones
A estas alturas ya estás muy familiarizado con la declaración de funciones, la función de expresión, la función de flecha y la función anónima. En este reto tendemos a utilizar la función de flecha en lugar de otras funciones. La función flecha no sustituye a otras funciones. Además, las funciones de flecha y las declaraciones de función no son exactamente iguales. Por lo tanto, debes saber cuándo usarla y cuándo no. En otras secciones trataré la diferencia en detalle. Utilizaremos el retorno explícito en lugar del implícito si la función es de una sola línea.
```js
// función que devuelve el nombre completo de una persona
const printFullName = (firstName, lastName) => firstName + " " + lastName;
// función que calcula el cuadrado de un número
const square = (n) => n * n;
// una función que genera colores hexa al azar
const hexaColor = () => {
const str = "0123456789abcdef";
let hexa = "#";
let index;
for (let i = 0; i < 6; i++) {
index = Math.floor(Math.random() * str.length);
hexa += str[index];
}
return hexa;
};
// una función que muestra la fecha y la hora
const showDateTime = () => {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const date = now.getDate();
let hours = now.getHours();
let minutes = now.getMinutes();
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
const dateMonthYear = date + "." + month + "." + year;
const time = hours + ":" + minutes;
const fullTime = dateMonthYear + " " + time;
return fullTime;
};
```
La función `new Dat().toLocaleString()` también puede utilizarse para mostrar la fecha y hora actuales. Los métodos `toLocaleString()` toman diferentes argumentos. Puede aprender más sobre la fecha y la hora en este [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString).
#### Bucles
En estos retos cubrimos muchos tipos de bucles. El bucle regular for, el bucle while, el bucle do while, el bucle for of, el bucle forEach y el bucle for in.
Veamos cómo los utilizamos:
```js
for (let i = 0; i < n; i++) {
console.log();
}
// declaración de una variable array
const names = ["Asabeneh", "Mathias", "Elias", "Brook"];
// iteración de un array mediante un bucle for regular
let len = names.length;
for (let i = 0; i < len; i++) {
console.log(names[i].toUpperCase());
}
// iteración de un array mediante for of
for (const name of names) {
console.log(name.toUpperCase());
}
// iteración de un array mediante forEach
names.forEach((name) => name.toUpperCase());
const person = {
firstName: "Asabeneh",
lastName: "Yetayeh",
age: 250,
country: "Finland",
city: "Helsinki",
skills: [
"HTML",
"CSS",
"JavaScript",
"React",
"Node",
"MongoDB",
"Python",
"D3.js",
],
isMarried: true,
};
for (const key in person) {
console.log(key);
}
```
#### Objetos
Declaramos el objeto literal con _const_.
```js
// declarando el objeto literal
const person = {
firstName: "Asabeneh",
lastName: "Yetayeh",
age: 250,
country: "Finland",
city: "Helsinki",
skills: [
"HTML",
"CSS",
"JavaScript",
"TypeScript",
"React",
"Node",
"MongoDB",
"Python",
"D3.js",
],
isMarried: true,
};
// iterar a través de las claves del objeto
for (const key in person) {
console.log(key, person[key]);
}
```
#### Condicional
Hemos dicho if, if else, else, switch y operadores ternarios en los retos anteriores.
```js
// sintaxis
if (condition) {
// esta parte del código se ejecuta para la condición de verdad
} else {
// esta parte del código se ejecuta para una condición falsa
}
```
```js
// if else
let num = 3;
if (num > 0) {
console.log(`${num} is a positive number`);
} else {
console.log(`${num} is a negative number`);
}
// 3 is a positive number
```
```js
// if else if else if else
let a = 0;
if (a > 0) {
console.log(`${a} is a positive number`);
} else if (a < 0) {
console.log(`${a} is a negative number`);
} else if (a == 0) {
console.log(`${a} is zero`);
} else {
console.log(`${a} is not a number`);
}
```
```js
// Switch Más Ejemplos
let dayUserInput = prompt("What day is today ?");
let day = dayUserInput.toLowerCase();
switch (day) {
case "monday":
console.log("Today is Monday");
break;
case "tuesday":
console.log("Today is Tuesday");
break;
case "wednesday":
console.log("Today is Wednesday");
break;
case "thursday":
console.log("Today is Thursday");
break;
case "friday":
console.log("Today is Friday");
break;
case "saturday":
console.log("Today is Saturday");
break;
case "sunday":
console.log("Today is Sunday");
break;
default:
console.log("It is not a week day.");
}
```
```js
// ternario
let isRaining = true;
isRaining
? console.log("You need a rain coat.")
: console.log("No need for a rain coat.");
```
#### Clases
Declaramos la clase con CamelCase que empieza con mayúscula.
```js
// sintaxis
class ClassName {
// el código va aquí
}
```
```js
// definir la clase
class Person {
constructor(firstName, lastName) {
console.log(this); // Compruebe el resultado desde aquí
this.firstName = firstName;
this.lastName = lastName;
}
}
```
Sea cual sea la guía de estilo que sigas, sé coherente. Sigue algunos paradigmas de programación y patrones de diseño. Recuerda que si no escribes tu código en cierto orden o forma, será difícil leerlo. Así que hazte un favor a ti mismo o a alguien que vaya a leer tu código escribiendo código legible.
🌕 Eres ordenado. Ahora, has aprendido a escribir un código limpio, para que cualquiera que conozca el idioma inglés pueda entender tu código.Siempre estás progresando y llevas 20 pasos en tu camino hacia la grandeza.
🎉 ¡FELICITACIONES! 🎉
[<< Día 19](../dia_19_Closures/dia_19_closures.md) | [Día 21 >>](..)
Loading…
Cancel
Save