diff --git a/Spanish/dia_17_Web_storages/dia_17_web_storages.md b/Spanish/dia_17_Web_storages/dia_17_web_storages.md index 069a713..64d8694 100644 --- a/Spanish/dia_17_Web_storages/dia_17_web_storages.md +++ b/Spanish/dia_17_Web_storages/dia_17_web_storages.md @@ -14,7 +14,7 @@ -[<< 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) diff --git a/Spanish/dia_18_Promesas/dia_18_Promesas.md b/Spanish/dia_18_Promesas/dia_18_Promesas.md new file mode 100644 index 0000000..8af01c8 --- /dev/null +++ b/Spanish/dia_18_Promesas/dia_18_Promesas.md @@ -0,0 +1,273 @@ +
+

30 Días de JavaScript: Promesas

+ + + + + Twitter Follow + + +Autor: +Asabeneh Yetayeh
+ Enero, 2020 +
+ +
+ +[<< 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 {: 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) diff --git a/Spanish/dia_19_Closures/dia_19_closures.md b/Spanish/dia_19_Closures/dia_19_closures.md new file mode 100644 index 0000000..d9be01e --- /dev/null +++ b/Spanish/dia_19_Closures/dia_19_closures.md @@ -0,0 +1,105 @@ +
+

30 Días de JavaScript: Closures

+ + + + + Twitter Follow + + +Autor: +Asabeneh Yetayeh
+ Enero, 2020 +
+ +
+ +[<< 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) diff --git a/Spanish/dia_20_Escribiendo_Codigos_Limpios/dia_20_escribiendo_codigos_limpios.md b/Spanish/dia_20_Escribiendo_Codigos_Limpios/dia_20_escribiendo_codigos_limpios.md new file mode 100644 index 0000000..b645d5d --- /dev/null +++ b/Spanish/dia_20_Escribiendo_Codigos_Limpios/dia_20_escribiendo_codigos_limpios.md @@ -0,0 +1,376 @@ +
+

30 Días de JavaScript: Escribiendo Códigos Limpios

+ + + + + Twitter Follow + + +Autor: +Asabeneh Yetayeh
+ Enero, 2020 +
+ +
+ +[<< 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 >>](..)