diff --git a/Spanish/dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md b/Spanish/dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md index 70ec130f..973c180c 100644 --- a/Spanish/dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md +++ b/Spanish/dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md @@ -14,7 +14,7 @@ -[<< Día 13](../dia_13_Metodos_del_Objeto_Console/dia_13_metodos_del_objeto_console.md) | [Día 15>>](..) +[<< Día 13](../dia_13_Metodos_del_Objeto_Console/dia_13_metodos_del_objeto_console.md) | [Día 15>>](../dia_15_Clases/dia_15_clases.md) ![Thirty Days Of JavaScript](../images/banners/day_1_14.png) @@ -190,4 +190,4 @@ Practica 🎉 ¡FELICITACIONES! 🎉 -[<< Día 13](../dia_13_Metodos_del_Objeto_Console/dia_13_metodos_del_objeto_console.md) | [Día 15>>](..) +[<< Día 13](../dia_13_Metodos_del_Objeto_Console/dia_13_metodos_del_objeto_console.md) | [Día 15>>](../dia_15_Clases/dia_15_clases.md) diff --git a/Spanish/dia_15_Clases/dia_15_clases.md b/Spanish/dia_15_Clases/dia_15_clases.md new file mode 100644 index 00000000..d0f0cb1a --- /dev/null +++ b/Spanish/dia_15_Clases/dia_15_clases.md @@ -0,0 +1,715 @@ +
+ +[<< Día 14](../dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md) | [Día 16>>](../dia_16_JSON/dia_16_json.md) + +![Thirty Days Of JavaScript](../images/banners/day_1_15.png) + +- [Día 15](#día-15) + - [Clases](#clases) + - [Definir una clase](#definir-una-clase) + - [Instanciar Clases](#instanciar-clases) + - [Constructor](#constructor) + - [Valores por defecto con el constructor](#valores-por-defecto-con-el-constructor) + - [Métodos de clase](#métodos-de-clase) + - [Propiedades con valor inicial](#propiedades-con-valor-inicial) + - [getter](#getter) + - [setter](#setter) + - [Método Static](#método-static) + - [Herencia](#herencia) + - [Anulación de métodos](#anulación-de-métodos) + - [Ejercicios](#ejercicios) + - [Ejercicios Nivel 1](#ejercicios-nivel-1) + - [Ejercicios Nivel 2](#ejercicios-nivel-2) + - [Ejercicios Nivel 3](#ejercicios-nivel-3) + +# Día 15 + +## Clases + +JavaScript es un lenguaje de programación orientado a objetos. Todo en JavScript es un objeto, con sus propiedades y métodos. Creamos una clase para crear un objeto. Una clase es como un constructor de objetos, o un "plano" para crear objetos. Instanciamos una clase para crear un objeto. La clase define los atributos y el comportamiento del objeto, mientras que el objeto, por su parte, representa la clase. + +Una vez que creamos una clase podemos crear un objeto a partir de ella cuando queramos. La creación de un objeto a partir de una clase se denomina instanciación de la clase. + +En la sección de objetos, vimos cómo crear un objeto literal. El objeto literal es un singleton (instancia única). Si queremos obtener un objeto similar, tenemos que escribirlo. Sin embargo, la clase permite crear muchos objetos. Esto ayuda a reducir la cantidad de código y la repetición del mismo. + +### Definir una clase + +Para definir una clase en JavaScript necesitamos la palabra clave _class_ , el nombre de una clase en **CamelCase** y bloque de código (dentro de dos corchetes). Vamos a crear una clase llamada Persona. + +```sh +// sintaxis +class ClassName { + // el código va aquí +} + +``` + +**Ejemplo:** + +```js +class Person { + // el código va aquí +} +``` + +Hemos creado una clase Persona pero no tiene nada dentro. + +### Instanciar Clases + +Instanciar una clase significa crear un objeto a partir de una clase. Necesitamos la palabra clave _new_ y llamamos al nombre de la clase después de la palabra _new_. + +Vamos a crear un objeto persona a partir de nuestra clase Persona. + +```js +class Person { + // el código va aquí +} +const person = new Person(); +console.log(person); +``` + +```sh +Person {} +``` + +Como puedes ver, hemos creado un objeto persona. Como la clase aún no tiene propiedades, el objeto también está vacío. + +Usemos el constructor de la clase para pasar diferentes propiedades a la clase. + +### Constructor + +El constructor es una función incorporada que permite crear un blueprint para nuestro objeto. La función constructora comienza con la palabra clave _constructor_ seguida de un paréntesis. Dentro del paréntesis pasamos las propiedades del objeto como parámetro. Utilizamos la palabra clave _this_ para adjuntar los parámetros del constructor con la clase. + +El siguiente constructor de la clase Persona tiene las propiedades firstName y lastName. Estas propiedades se adjuntan a la clase Persona utilizando la palabra clave _this_. _this_ se refiere a la propia clase. + +```js +class Person { + constructor(firstName, lastName) { + console.log(this); // Compruebe el resultado desde aquí + this.firstName = firstName; + this.lastName = lastName; + } +} + +const person = new Person(); + +console.log(person); +``` + +```sh +Person {firstName: undefined, lastName:undefined} +``` + +Todas las claves del objeto son undefined. Siempre que instanciemos debemos pasar el valor de las propiedades. Pasemos el valor en este momento cuando instanciamos la clase. + +```js +class Person { + constructor(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh"); + +console.log(person1); +``` + +```sh +Person {firstName: "Asabeneh", lastName: "Yetayeh"} +``` + +Como hemos dicho al principio, una vez que creamos una clase podemos crear muchos objetos utilizando la clase. Ahora, vamos a crear muchos objetos persona utilizando la clase Persona. + +```js +class Person { + constructor(firstName, lastName) { + console.log(this); // Compruebe el resultado desde aquí + this.firstName = firstName; + this.lastName = lastName; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh"); +const person2 = new Person("Lidiya", "Tekle"); +const person3 = new Person("Abraham", "Yetayeh"); + +console.log(person1); +console.log(person2); +console.log(person3); +``` + +```sh +Person {firstName: "Asabeneh", lastName: "Yetayeh"} +Person {firstName: "Lidiya", lastName: "Tekle"} +Person {firstName: "Abraham", lastName: "Yetayeh"} +``` + +Usando la clase Persona creamos tres objetos persona. Como puedes ver nuestra clase no tenía muchas propiedades vamos a añadir más propiedades a la clase. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + console.log(this); // Compruebe el resultado desde aquí + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); + +console.log(person1); +``` + +```sh +Person {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki"} +``` + +### Valores por defecto con el constructor + +Las propiedades de la función constructora pueden tener un valor por defecto como otras funciones regulares. + +```js +class Person { + constructor( + firstName = "Asabeneh", + lastName = "Yetayeh", + age = 250, + country = "Finland", + city = "Helsinki" + ) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + } +} + +const person1 = new Person(); // tomará el valor por defecto values +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); + +console.log(person1); +console.log(person2); +``` + +```sh +Person {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki"} +Person {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Espoo"} +``` + +### Métodos de clase + +El constructor dentro de una clase es una función incorporada que nos permite crear un blueprint para el objeto. En una clase podemos crear métodos de clase. Los métodos son funciones de JavaScript dentro de la clase. Vamos a crear algunos métodos de clase. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); + +console.log(person1.getFullName()); +console.log(person2.getFullName()); +``` + +```sh +Asabeneh Yetayeh +test.js:19 Lidiya Tekle +``` + +### Propiedades con valor inicial + +Cuando creamos una clase para algunas propiedades podemos tener un valor inicial. Por ejemplo, si estás jugando una partida, tu puntuación inicial será cero. Así, podemos tener una puntuación inicial o una puntuación que sea cero. De otra manera, podemos tener una habilidad inicial y adquiriremos alguna habilidad después de algún tiempo. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + this.score = 0; + this.skills = []; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); + +console.log(person1.score); +console.log(person2.score); + +console.log(person1.skills); +console.log(person2.skills); +``` + +```sh +0 +0 +[] +[] +``` + +Un método puede ser un método regular o un getter o un setter. Veamos, getter y setter. + +### getter + +El método get nos permite acceder al valor del objeto. Escribimos un método get utilizando la palabra clave _get_ seguida de una función. En lugar de acceder a las propiedades directamente desde el objeto utilizamos getter para obtener el valor. Vea el ejemplo siguiente + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + this.score = 0; + this.skills = []; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } + get getScore() { + return this.score; + } + get getSkills() { + return this.skills; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); + +console.log(person1.getScore); // No necesitamos paréntesis para llamar a un método getter +console.log(person2.getScore); + +console.log(person1.getSkills); +console.log(person2.getSkills); +``` + +```sh +0 +0 +[] +[] +``` + +### setter + +El método setter nos permite modificar el valor de ciertas propiedades. Escribimos un método setter utilizando la palabra clave _set_ seguida de una función. Vea el ejemplo de abajo. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + this.score = 0; + this.skills = []; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } + get getScore() { + return this.score; + } + get getSkills() { + return this.skills; + } + set setScore(score) { + this.score += score; + } + set setSkill(skill) { + this.skills.push(skill); + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); + +person1.setScore = 1; +person1.setSkill = "HTML"; +person1.setSkill = "CSS"; +person1.setSkill = "JavaScript"; + +person2.setScore = 1; +person2.setSkill = "Planning"; +person2.setSkill = "Managing"; +person2.setSkill = "Organizing"; + +console.log(person1.score); +console.log(person2.score); + +console.log(person1.skills); +console.log(person2.skills); +``` + +```sh +1 +1 +["HTML", "CSS", "JavaScript"] +["Planning", "Managing", "Organizing"] +``` + +No te confundas con la diferencia entre un método regular y un getter. If you know how to make a regular method you are good. Let us add regular method called getPersonInfo in the Person class. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + this.score = 0; + this.skills = []; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } + get getScore() { + return this.score; + } + get getSkills() { + return this.skills; + } + set setScore(score) { + this.score += score; + } + set setSkill(skill) { + this.skills.push(skill); + } + getPersonInfo() { + let fullName = this.getFullName(); + let skills = + this.skills.length > 0 && + this.skills.slice(0, this.skills.length - 1).join(", ") + + ` and ${this.skills[this.skills.length - 1]}`; + let formattedSkills = skills ? `He knows ${skills}` : ""; + + let info = `${fullName} is ${this.age}. He lives ${this.city}, ${this.country}. ${formattedSkills}`; + return info; + } +} + +const person1 = new Person("Asabeneh", "Yetayeh", 250, "Finland", "Helsinki"); +const person2 = new Person("Lidiya", "Tekle", 28, "Finland", "Espoo"); +const person3 = new Person("John", "Doe", 50, "Mars", "Mars city"); + +person1.setScore = 1; +person1.setSkill = "HTML"; +person1.setSkill = "CSS"; +person1.setSkill = "JavaScript"; + +person2.setScore = 1; +person2.setSkill = "Planning"; +person2.setSkill = "Managing"; +person2.setSkill = "Organizing"; + +console.log(person1.getScore); +console.log(person2.getScore); + +console.log(person1.getSkills); +console.log(person2.getSkills); +console.log(person3.getSkills); + +console.log(person1.getPersonInfo()); +console.log(person2.getPersonInfo()); +console.log(person3.getPersonInfo()); +``` + +```sh +1 +1 +["HTML", "CSS", "JavaScript"] +["Planning", "Managing", "Organizing"] +[] +Asabeneh Yetayeh is 250. He lives Helsinki, Finland. He knows HTML, CSS and JavaScript +Lidiya Tekle is 28. He lives Espoo, Finland. He knows Planning, Managing and Organizing +John Doe is 50. He lives Mars city, Mars. +``` + +### Método Static + +La palabra clave static define un método estático para una clase. Los métodos estáticos no se llaman en las instancias de la clase. En cambio, se llaman en la propia clase. A menudo se trata de funciones de utilidad, como las funciones para crear o clonar objetos. Un ejemplo de método estático es _Date.now()_. El método _now_ se llama directamente desde la clase. + +```js +class Person { + constructor(firstName, lastName, age, country, city) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.country = country; + this.city = city; + this.score = 0; + this.skills = []; + } + getFullName() { + const fullName = this.firstName + " " + this.lastName; + return fullName; + } + get getScore() { + return this.score; + } + get getSkills() { + return this.skills; + } + set setScore(score) { + this.score += score; + } + set setSkill(skill) { + this.skills.push(skill); + } + getPersonInfo() { + let fullName = this.getFullName(); + let skills = + this.skills.length > 0 && + this.skills.slice(0, this.skills.length - 1).join(", ") + + ` and ${this.skills[this.skills.length - 1]}`; + + let formattedSkills = skills ? `He knows ${skills}` : ""; + + let info = `${fullName} is ${this.age}. He lives ${this.city}, ${this.country}. ${formattedSkills}`; + return info; + } + static favoriteSkill() { + const skills = ["HTML", "CSS", "JS", "React", "Python", "Node"]; + const index = Math.floor(Math.random() * skills.length); + return skills[index]; + } + static showDateTime() { + let now = new Date(); + let year = now.getFullYear(); + let month = now.getMonth() + 1; + let date = now.getDate(); + let hours = now.getHours(); + let minutes = now.getMinutes(); + if (hours < 10) { + hours = "0" + hours; + } + if (minutes < 10) { + minutes = "0" + minutes; + } + + let dateMonthYear = date + "." + month + "." + year; + let time = hours + ":" + minutes; + let fullTime = dateMonthYear + " " + time; + return fullTime; + } +} + +console.log(Person.favoriteSkill()); +console.log(Person.showDateTime()); +``` + +```sh +Node +15.1.2020 23:56 +``` + +Los métodos estáticos son métodos que pueden ser utilizados como funciones de utilidad. + +## Herencia + +Utilizando la herencia podemos acceder a todas las propiedades y métodos de la clase padre. Esto reduce la repetición de código. Si recuerdas, tenemos una clase padre Persona y crearemos hijos a partir de ella. Nuestra clase de niños podría ser estudiante, enseñar, etc. + +```js +// sintaxis +class ChildClassName extends { + // el código va aquí +} +``` + +Vamos a crear una clase hija Student a partir de la clase padre Person. + +```js +class Student extends Person { + saySomething() { + console.log("I am a child of the person class"); + } +} + +const s1 = new Student("Asabeneh", "Yetayeh", "Finland", 250, "Helsinki"); +console.log(s1); +console.log(s1.saySomething()); +console.log(s1.getFullName()); +console.log(s1.getPersonInfo()); +``` + +```sh +Student {firstName: "Asabeneh", lastName: "Yetayeh", age: "Finland", country: 250, city: "Helsinki", …} +I am a child of the person class +Asabeneh Yetayeh +Student {firstName: "Asabeneh", lastName: "Yetayeh", age: "Finland", country: 250, city: "Helsinki", …} +Asabeneh Yetayeh is Finland. He lives Helsinki, 250. +``` + +### Anulación de métodos + +Como puedes ver, conseguimos acceder a todos los métodos de la clase Persona y lo utilizamos en la clase hija Student. Podemos personalizar los métodos padre, podemos añadir propiedades adicionales a una clase hija. Si queremos personalizar, los métodos y si queremos añadir propiedades extra, necesitamos usar la función del constructor la clase hija también. Dentro de la función constructora llamamos a la función super() para acceder a todas las propiedades de la clase padre. La clase Persona no tenía género pero ahora vamos a dar la propiedad género para la clase hija, Student. Si se utiliza el mismo nombre de método en la clase hija, se anulará el método padre. + +```js +class Student extends Person { + constructor(firstName, lastName, age, country, city, gender) { + super(firstName, lastName, age, country, city); + this.gender = gender; + } + + saySomething() { + console.log("I am a child of the person class"); + } + getPersonInfo() { + let fullName = this.getFullName(); + let skills = + this.skills.length > 0 && + this.skills.slice(0, this.skills.length - 1).join(", ") + + ` and ${this.skills[this.skills.length - 1]}`; + + let formattedSkills = skills ? `He knows ${skills}` : ""; + let pronoun = this.gender == "Male" ? "He" : "She"; + + let info = `${fullName} is ${this.age}. ${pronoun} lives in ${this.city}, ${this.country}. ${formattedSkills}`; + return info; + } +} + +const s1 = new Student( + "Asabeneh", + "Yetayeh", + 250, + "Finland", + "Helsinki", + "Male" +); +const s2 = new Student("Lidiya", "Tekle", 28, "Finland", "Helsinki", "Female"); +s1.setScore = 1; +s1.setSkill = "HTML"; +s1.setSkill = "CSS"; +s1.setSkill = "JavaScript"; + +s2.setScore = 1; +s2.setSkill = "Planning"; +s2.setSkill = "Managing"; +s2.setSkill = "Organizing"; + +console.log(s1); + +console.log(s1.saySomething()); +console.log(s1.getFullName()); +console.log(s1.getPersonInfo()); + +console.log(s2.saySomething()); +console.log(s2.getFullName()); +console.log(s2.getPersonInfo()); +``` + +```sh +Student {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki", …} +Student {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Helsinki", …} +I am a child of the person class +Asabeneh Yetayeh +Student {firstName: "Asabeneh", lastName: "Yetayeh", age: 250, country: "Finland", city: "Helsinki", …} +Asabeneh Yetayeh is 250. He lives in Helsinki, Finland. He knows HTML, CSS and JavaScript +I am a child of the person class +Lidiya Tekle +Student {firstName: "Lidiya", lastName: "Tekle", age: 28, country: "Finland", city: "Helsinki", …} +Lidiya Tekle is 28. She lives in Helsinki, Finland. He knows Planning, Managing and Organizing +``` + +Ahora, el método getPersonInfo ha sido anulado e identifica si la persona es hombre o mujer. + +🌕 Eres excelente. Ahora, usted conoce las clases y tiene el poder de convertir todo en un objeto. Has llegado a la mitad de tu camino hacia la grandeza. Ahora haz algunos ejercicios para tu cerebro y para tu músculo. + +## Ejercicios + +### Ejercicios Nivel 1 + +1. Crea una clase de Animal. La clase tendrá propiedades de nombre, edad, color, piernas y creará diferentes métodos. +2. Cree una clase hijo de Perro y Gato a partir de la Clase Animal. + +### Ejercicios Nivel 2 + +1. Sobrescribir el método que se crea en la clase Animal. + +### Ejercicios Nivel 3 + +1. Intentemos desarrollar un programa que calcule la medida de tendencia central de una muestra (media, mediana, moda) y la medida de variabilidad (rango, variación, desviación estándar). Además de esas medidas, encuentre el mínimo, el máximo, el recuento, el porcentaje y la distribución de frecuencias de la muestra. Puedes crear una clase llamada Statistics y crear todas las funciones que hacen cálculos estadísticos como método para la clase Statistics. Comprueba el resultado que aparece a continuación. + +```JS +ages = [31, 26, 34, 37, 27, 26, 32, 32, 26, 27, 27, 24, 32, 33, 27, 25, 26, 38, 37, 31, 34, 24, 33, 29, 26] + +console.log('Count:', statistics.count()) // 25 +console.log('Sum: ', statistics.sum()) // 744 +console.log('Min: ', statistics.min()) // 24 +console.log('Max: ', statistics.max()) // 38 +console.log('Range: ', statistics.range() // 14 +console.log('Mean: ', statistics.mean()) // 30 +console.log('Median: ',statistics.median()) // 29 +console.log('Mode: ', statistics.mode()) // {'mode': 26, 'count': 5} +console.log('Variance: ',statistics.var()) // 17.5 +console.log('Standard Deviation: ', statistics.std()) // 4.2 +console.log('Variance: ',statistics.var()) // 17.5 +console.log('Frequency Distribution: ',statistics.freqDist()) // [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)] +``` + +```sh +// el resultado debería ser el siguiente +console.log(statistics.describe()) +Count: 25 +Sum: 744 +Min: 24 +Max: 38 +Range: 14 +Mean: 30 +Median: 29 +Mode: (26, 5) +Variance: 17.5 +Standard Deviation: 4.2 +Frequency Distribution: [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)] +``` + +1. Crea una clase llamada PersonAccount. Tiene propiedades de nombre, apellido, ingresos, gastos y tiene métodos 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 y su descripción. + +🎉 ¡FELICITACIONES! 🎉 + +[<< Día 14](../dia_14_Manejo_de_Errores/dia_14_manejo_de_errores.md) | [Día 16>>](../dia_16_JSON/dia_16_json.md) diff --git a/Spanish/dia_16_JSON/dia_16_json.md b/Spanish/dia_16_JSON/dia_16_json.md new file mode 100644 index 00000000..c95fd731 --- /dev/null +++ b/Spanish/dia_16_JSON/dia_16_json.md @@ -0,0 +1,602 @@ + + +[<< Día 15](../dia_15_Clases/dia_15_clases.md) | [Día 17 >>](../dia_17_Web_storages/dia_17_web_storages.md) + +![Thirty Days Of JavaScript](../images/banners/day_1_16.png) + +- [Día 16](#día-16) + - [JSON](#json) + - [Convertir JSON en objeto JavaScript](#convertir-json-en-objeto-javascript) + - [JSON.parse()](#jsonparse) + - [Uso de una función de recuperación con JSON.parse()](#uso-de-una-función-de-recuperación-con-jsonparse) + - [Conversión de objetos a JSON](#conversión-de-objetos-a-json) + - [Usando un filtro de array con JSON.stringify](#usando-un-filtro-de-array-con-jsonstringify) + - [Ejercicios](#ejercicios) + - [Ejercicios Nivel 1](#ejercicios-nivel-1) + - [Ejercicios Nivel 2](#ejercicios-nivel-2) + - [Ejercicios Nivel 3](#ejercicios-nivel-3) + +# Día 16 + +## JSON + +JSON son las siglas de JavaScript Object Notation (Notación de objetos de JavaScript). La sintaxis JSON se deriva de la sintaxis de notación de objetos de JavaScript, pero el formato JSON es sólo de texto o cadena. JSON es un formato de datos ligero para almacenar y transportar. JSON se utiliza sobre todo cuando se envían datos de un servidor a un cliente. JSON es una alternativa más fácil de usar que XML. + +**Ejemplo:** + +```js +{ +"users":[ + { + "firstName":"Asabeneh", + "lastName":"Yetayeh", + "age":250, + "email":"asab@asb.com" + }, + { + "firstName":"Alex", + "lastName":"James", + "age":25, + "email":"alex@alex.com" + }, + { + "firstName":"Lidiya", + "lastName":"Tekle", + "age":28, + "email":"lidiya@lidiya.com" + } +] +} +``` + +El ejemplo JSON anterior no es muy diferente de un objeto normal. Entonces, ¿cuál es la diferencia? La diferencia es que la clave de un objeto JSON debe ir con comillas dobles o debe ser una cadena. JavaScript Object y JSON son muy similares por lo que podemos cambiar JSON a Object y Object a JSON. + +Veamos el ejemplo anterior con más detalle, comienza con una llave. Dentro de la corchete, hay una clave "usuarios" que tiene una matriz de valores. Dentro del array tenemos diferentes objetos y cada objeto tiene claves, cada clave tiene que tener comillas dobles. Por ejemplo, utilizamos "firstNaMe" en lugar de sólo firstName, sin embargo en el objeto utilizamos claves sin comillas dobles. Esta es la mayor diferencia entre un objeto y un JSON. Veamos más ejemplos sobre JSON. + +**Ejemplo:** + +```js +{ + "Alex": { + "email": "alex@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript" + ], + "age": 20, + "isLoggedIn": false, + "points": 30 + }, + "Asab": { + "email": "asab@asab.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Redux", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 25, + "isLoggedIn": false, + "points": 50 + }, + "Brook": { + "email": "daniel@daniel.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux" + ], + "age": 30, + "isLoggedIn": true, + "points": 50 + }, + "Daniel": { + "email": "daniel@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Python" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "John": { + "email": "john@john.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux", + "Node.js" + ], + "age": 20, + "isLoggedIn": true, + "points": 50 + }, + "Thomas": { + "email": "thomas@thomas.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "Paul": { + "email": "paul@paul.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + } +} +``` + +### Convertir JSON en objeto JavaScript + +La mayoría de las veces obtenemos los datos JSON de la respuesta HTTP o de un archivo, pero podemos almacenar el JSON como una cadena y podemos cambiarlo por un objeto para la demostración. En JavaScript la palabra clave _JSON_ tiene los métodos _parse()_ y _stringify()_. Cuando queremos cambiar el JSON a un objeto, parseamos el JSON usando _JSON.parse()_. Cuando queremos pasar el objeto a JSON utilizamos _JSON.stringify()_. + +#### JSON.parse() + +```js +JSON.parse(json[, reviver]) +// json or text , los datos +//reviver es una función opcional de callback +/* JSON.parse(json, (key, value) => { + +}) +*/ +``` + +```js +const usersText = `{ +"users":[ + { + "firstName":"Asabeneh", + "lastName":"Yetayeh", + "age":250, + "email":"asab@asb.com" + }, + { + "firstName":"Alex", + "lastName":"James", + "age":25, + "email":"alex@alex.com" + }, + { + "firstName":"Lidiya", + "lastName":"Tekle", + "age":28, + "email":"lidiya@lidiya.com" + } +] +}`; + +const usersObj = JSON.parse(usersText, undefined, 4); +console.log(usersObj); +``` + +### Uso de una función de recuperación con JSON.parse() + +Para utilizar la función reviver como formateador, ponemos las claves que queremos para formatear el valor del nombre y del apellido. Digamos que estamos interesados en formatear el nombre y el apellido de los datos JSON. + +```js +const usersText = `{ +"users":[ + { + "firstName":"Asabeneh", + "lastName":"Yetayeh", + "age":250, + "email":"asab@asb.com" + }, + { + "firstName":"Alex", + "lastName":"James", + "age":25, + "email":"alex@alex.com" + }, + { + "firstName":"Lidiya", + "lastName":"Tekle", + "age":28, + "email":"lidiya@lidiya.com" + } +] +}`; + +const usersObj = JSON.parse(usersText, (key, value) => { + let newValue = + typeof value == "string" && key != "email" ? value.toUpperCase() : value; + return newValue; +}); +console.log(usersObj); +``` + +El _JSON.parse()_ es muy práctico de usar. No tienes que pasar el parámetro opcional, puedes simplemente usarlo con el parámetro requerido y lograrás bastante. + +### Conversión de objetos a JSON + +Cuando queremos pasar el objeto a JSON utilizamos _JSON.stringify()_. El método stringify toma un parámetro obligatorio y dos opcionales. _Replacer_ se utiliza como filtro y _space_ es una indentación. Si no queremos filtrar ninguna de las claves del objeto podemos pasar simplemente undefined. + +```js +JSON.stringify(obj, replacer, space); +// json or text , los datos +// reviver es una función opcional de callback +``` + +Convirtamos el siguiente objeto en una cadena. Primero mantengamos todas las claves y también tengamos una indentación de 4 espacios. + +```js +const users = { + Alex: { + email: "alex@alex.com", + skills: ["HTML", "CSS", "JavaScript"], + age: 20, + isLoggedIn: false, + points: 30, + }, + Asab: { + email: "asab@asab.com", + skills: [ + "HTML", + "CSS", + "JavaScript", + "Redux", + "MongoDB", + "Express", + "React", + "Node", + ], + age: 25, + isLoggedIn: false, + points: 50, + }, + Brook: { + email: "daniel@daniel.com", + skills: ["HTML", "CSS", "JavaScript", "React", "Redux"], + age: 30, + isLoggedIn: true, + points: 50, + }, + Daniel: { + email: "daniel@alex.com", + skills: ["HTML", "CSS", "JavaScript", "Python"], + age: 20, + isLoggedIn: false, + points: 40, + }, + John: { + email: "john@john.com", + skills: ["HTML", "CSS", "JavaScript", "React", "Redux", "Node.js"], + age: 20, + isLoggedIn: true, + points: 50, + }, + Thomas: { + email: "thomas@thomas.com", + skills: ["HTML", "CSS", "JavaScript", "React"], + age: 20, + isLoggedIn: false, + points: 40, + }, + Paul: { + email: "paul@paul.com", + skills: [ + "HTML", + "CSS", + "JavaScript", + "MongoDB", + "Express", + "React", + "Node", + ], + age: 20, + isLoggedIn: false, + points: 40, + }, +}; + +const txt = JSON.stringify(users, undefined, 4); +console.log(txt); // text significa JSON- porque json es una forma de cadena de un objeto. +``` + +```sh +{ + "Alex": { + "email": "alex@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript" + ], + "age": 20, + "isLoggedIn": false, + "points": 30 + }, + "Asab": { + "email": "asab@asab.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Redux", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 25, + "isLoggedIn": false, + "points": 50 + }, + "Brook": { + "email": "daniel@daniel.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux" + ], + "age": 30, + "isLoggedIn": true, + "points": 50 + }, + "Daniel": { + "email": "daniel@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Python" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "John": { + "email": "john@john.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux", + "Node.js" + ], + "age": 20, + "isLoggedIn": true, + "points": 50 + }, + "Thomas": { + "email": "thomas@thomas.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "Paul": { + "email": "paul@paul.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + } +} +``` + +### Usando un filtro de array con JSON.stringify + +Ahora, vamos a utilizar replacer como un filtro. El objeto usuario tiene una larga lista de claves, pero sólo nos interesan algunas de ellas. Ponemos las claves que queremos conservar en un array como se muestra en el ejemplo y lo utilizamos en lugar del replacer. + +```js +const user = { + firstName: "Asabeneh", + lastName: "Yetayeh", + country: "Finland", + city: "Helsinki", + email: "alex@alex.com", + skills: ["HTML", "CSS", "JavaScript", "React", "Python"], + age: 250, + isLoggedIn: false, + points: 30, +}; + +const txt = JSON.stringify( + user, + ["firstName", "lastName", "country", "city", "age"], + 4 +); +console.log(txt); +``` + +```sh +{ + "firstName": "Asabeneh", + "lastName": "Yetayeh", + "country": "Finland", + "city": "Helsinki", + "age": 250 +} +``` + +🌕 Eres extraordinario. Ahora, ya conoces un formato de datos ligero que puedes utilizar para almacenar datos o para enviarlos a un servidor HTTP. Llevas 16 pasos de ventaja en tu camino hacia la grandeza. Ahora haz algunos ejercicios para tu cerebro y para tus músculos. + +## Ejercicios + +```js +const skills = ["HTML", "CSS", "JS", "React", "Node", "Python"]; +let age = 250; +let isMarried = true; +const student = { + firstName: "Asabeneh", + lastName: "Yetayehe", + age: 250, + isMarried: true, + skills: ["HTML", "CSS", "JS", "React", "Node", "Python"], +}; +const txt = `{ + "Alex": { + "email": "alex@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript" + ], + "age": 20, + "isLoggedIn": false, + "points": 30 + }, + "Asab": { + "email": "asab@asab.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Redux", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 25, + "isLoggedIn": false, + "points": 50 + }, + "Brook": { + "email": "daniel@daniel.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux" + ], + "age": 30, + "isLoggedIn": true, + "points": 50 + }, + "Daniel": { + "email": "daniel@alex.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "Python" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "John": { + "email": "john@john.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React", + "Redux", + "Node.js" + ], + "age": 20, + "isLoggedIn": true, + "points": 50 + }, + "Thomas": { + "email": "thomas@thomas.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "React" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + }, + "Paul": { + "email": "paul@paul.com", + "skills": [ + "HTML", + "CSS", + "JavaScript", + "MongoDB", + "Express", + "React", + "Node" + ], + "age": 20, + "isLoggedIn": false, + "points": 40 + } +} +`; +``` + +### Ejercicios Nivel 1 + +1. Cambiar el array de habilidades a JSON usando JSON.stringify() +1. Stringify la variable de la edad +1. Stringify la variable isMarried +1. Stringify el objeto estudiante + +### Ejercicios Nivel 2 + +1. Stringify el objeto estudiantes con sólo las propiedades firstName, lastName y skills + +### Ejercicios Nivel 3 + +1. Parsear el _txt_ JSON a objeto. +2. Encuentra el usuario que tiene muchas habilidades de la variable almacenada en _txt_. + +🎉 ¡FELICITACIONES! 🎉 + +[<< Día 15](../dia_15_Clases/dia_15_clases.md) | [Día 17 >>](../dia_17_Web_storages/dia_17_web_storages.md) diff --git a/Spanish/dia_17_Web_storages/dia_17_web_storages.md b/Spanish/dia_17_Web_storages/dia_17_web_storages.md new file mode 100644 index 00000000..069a713a --- /dev/null +++ b/Spanish/dia_17_Web_storages/dia_17_web_storages.md @@ -0,0 +1,233 @@ + + +[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](..) + +![Thirty Days Of JavaScript](../images/banners/day_1_17.png) + +- [Día 17](#día-17) + - [Storage (Almacenamiento) web HTML5](#storage-almacenamiento-web-html5) + - [sessionStorage](#sessionstorage) + - [localStorage](#localstorage) + - [Caso de uso de los almacenamientos web](#caso-de-uso-de-los-almacenamientos-web) + - [Objetos de almacenamiento web HTML5](#objetos-de-almacenamiento-web-html5) + - [Establecer el elemento en el localStorage](#establecer-el-elemento-en-el-localstorage) + - [Obtener un elemento de localStorage](#obtener-un-elemento-de-localstorage) + - [Limpiando el localStorage](#limpiando-el-localstorage) + - [Ejercicios](#ejercicios) + - [Ejercicios: Nivel 1](#ejercicios-nivel-1) + - [Ejercicios: Nivel 2](#ejercicios-nivel-2) + - [Ejercicios: Nivel 3](#ejercicios-nivel-3) + +# Día 17 + +## Storage (Almacenamiento) web HTML5 + +Web Storage (sessionStorage y localStorage) es una nueva API de HTML5 que ofrece importantes ventajas sobre las cookies tradicionales. Antes de HTML5, los datos de las aplicaciones debían almacenarse en cookies, incluidas en cada solicitud del servidor. Web storage es más seguro, y se pueden almacenar grandes cantidades de datos localmente, sin afectar al rendimiento del sitio web. El límite de almacenamiento de datos de las cookies en muchos navegadores web es de unos 4 KB por cookie. Nosotros almacenamos datos mucho más grandes (al menos 5MB) y nunca los transferimos al servidor. Todos los sitios del mismo o único origen pueden almacenar y acceder a los mismos datos. + +Se puede acceder a los datos almacenados mediante JavaScript, lo que permite aprovechar las secuencias de comandos del lado del cliente para hacer muchas cosas que tradicionalmente han implicado la programación del lado del servidor y las bases de datos relacionales. Hay dos objetos de almacenamiento web: + +- sessionStorage +- localStorage + +localStorage es similar a sessionStorage, excepto que mientras los datos almacenados en localStorage no tienen tiempo de caducidad, los datos almacenados en sessionStorage se borran cuando termina la sesión de la página, es decir, cuando se cierra la página. + +Hay que tener en cuenta que los datos almacenados en localStorage o sessionStorage son específicos del protocolo de la página. + +Las claves y los valores son siempre cadenas (tenga en cuenta que, al igual que con los objetos, las claves enteras se convertirán automáticamente en cadenas). + +![web_storage](../images/web_storage.png) + +### sessionStorage + +sessionStorage sólo está disponible dentro de la sesión de la pestaña o ventana del navegador. Está diseñado para almacenar datos en una sola sesión de la página web. Esto significa que si la ventana se cierra, los datos de la sesión se eliminarán. Como sessionStorage y localStorage tienen métodos similares, nos centraremos sólo en localStorage. + +### localStorage + +El localStorage de HTML5 es la para la API de almacenamiento web que se utiliza para almacenar datos en el navegador sin caducidad. Los datos estarán disponibles en el navegador incluso después de cerrarlo. localStorage se mantiene incluso entre sesiones del navegador. Esto significa que los datos siguen estando disponibles cuando se cierra y se vuelve a abrir el navegador, y también de forma instantánea entre pestañas y ventanas. + +En ambos casos, los datos del almacenamiento web no están disponibles entre distintos navegadores. Por ejemplo, no se puede acceder a los objetos de almacenamiento creados en Firefox en Internet Explorer, exactamente igual que las cookies. Hay cinco métodos para trabajar en el almacenamiento local: +_setItem(), getItem(), removeItem(), clear(), key()_ + +### Caso de uso de los almacenamientos web + +Algunos casos de uso de los almacenes web son + +- almacenar datos temporalmente. +- guardar los productos que el usuario pone en su carrito de la compra. +- los datos pueden estar disponibles entre peticiones de página, múltiples pestañas del navegador y también entre sesiones del navegador utilizando localStorage. +- puede utilizarse completamente sin conexión utilizando localStorage. +- El almacenamiento en la web puede suponer una gran ganancia de rendimiento cuando algunos datos estáticos se almacenan en el cliente para minimizar el número de peticiones posteriores. Incluso las imágenes pueden almacenarse en cadenas utilizando la codificación Base64. +- se puede utilizar para el método de autenticación del usuario. + +Para los ejemplos mencionados anteriormente, tiene sentido utilizar localStorage. Te preguntarás, entonces, cuándo debemos utilizar sessionStorage. + +En algunos casos, queremos deshacernos de los datos en cuanto se cierra la ventana. O, quizás, si no queremos que la aplicación interfiera con la misma aplicación que está abierta en otra ventana. Estos escenarios se sirven mejor con sessionStorage. + +Ahora, vamos a ver cómo hacer uso de estas APIs de almacenamiento web. + +## Objetos de almacenamiento web HTML5 + +El almacenamiento (storage) web HTML proporciona dos objetos para almacenar datos en el cliente: + +- window.localStorage - almacena datos sin fecha de caducidad +- window.sessionStorage - almacena datos para una sesión (los datos se pierden cuando se cierra la pestaña del navegador)La mayoría de los navegadores modernos soportan Web Storage, sin embargo es bueno comprobar el soporte del navegador para localStorage y sessionStorage. Veamos los métodos disponibles para los objetos Web Storage. + +Objetos Web Storage: + +- _localStorage_ - para mostrar el objeto localStorage +- _localStorage.clear()_ - para remover todo lo que hay en el almacenamiento local +- _localStorage.setItem()_ - para almacenar datos en el localStorage. Toma como parámetros una clave y un valor. +- _localStorage.getItem()_ - para mostrar los datos almacenados en el localStorage. Toma una clave como parámetro. +- _localStorage.removeItem()_ - para remover un ítem almacenado de un localStorage. Toma la clave como parámetro. +- _localStorage.key()_ - para mostrar un dato almacenado en un localStorage. Toma el índice como parámetro. + +![local_storage](../images/local_storage.png) + +### Establecer el elemento en el localStorage + +Cuando establecemos conjunto los datos que se almacenan en un localStorage, se almacenarán como una cadena. Si estamos almacenando un array o un objeto, debemos encadenarlo primero para mantener el formato, a menos que perdamos la estructura del array o del objeto de los datos originales. + +Almacenamos los datos en el localStorage utilizando el método _localStorage.setItem_. + +```js +//sintaxis +localStorage.setItem("key", "value"); +``` + +- Almacenamiento de una cadena en un localStorage + +```js +localStorage.setItem("firstName", "Asabeneh"); // ya que el valor es una cadena, no lo encadenamos +console.log(localStorage); +``` + +```sh +Storage {firstName: 'Asabeneh', length: 1} +``` + +- Almacenar el número en un storage local + +```js +localStorage.setItem("age", 200); +console.log(localStorage); +``` + +```sh + Storage {age: '200', firstName: 'Asabeneh', length: 2} +``` + +- Almacenando un array en un localStorage. Si estamos almacenando un array, un objeto o una matriz de objetos, debemos encadenar el objeto primero. Véase el ejemplo siguiente. + +```js +const skills = ["HTML", "CSS", "JS", "React"]; +//El array de Skills tiene que ser encadenado primero para mantener el formato. +const skillsJSON = JSON.stringify(skills, undefined, 4); +localStorage.setItem("skills", skillsJSON); +console.log(localStorage); +``` + +```sh +Storage {age: '200', firstName: 'Asabeneh', skills: 'HTML,CSS,JS,React', length: 3} +``` + +```js +let skills = [ + { tech: "HTML", level: 10 }, + { tech: "CSS", level: 9 }, + { tech: "JS", level: 8 }, + { tech: "React", level: 9 }, + { tech: "Redux", level: 10 }, + { tech: "Node", level: 8 }, + { tech: "MongoDB", level: 8 }, +]; + +let skillJSON = JSON.stringify(skills); +localStorage.setItem("skills", skillJSON); +``` + +- Almacenamiento de un objeto en un localStorage. Antes de almacenar los objetos en un localStorage, el objeto tiene que ser stringificado. + +```js +const user = { + firstName: "Asabeneh", + age: 250, + skills: ["HTML", "CSS", "JS", "React"], +}; + +const userText = JSON.stringify(user, undefined, 4); +localStorage.setItem("user", userText); +``` + +### Obtener un elemento de localStorage + +Obtenemos los datos del almacenamiento local utilizando el método _localStorage.getItem()_. + +```js +//sintaxis +localStorage.getItem("key"); +``` + +```js +let firstName = localStorage.getItem("firstName"); +let age = localStorage.getItem("age"); +let skills = localStorage.getItem("skills"); +console.log(firstName, age, skills); +``` + +```sh + 'Asabeneh', '200', '['HTML','CSS','JS','React']' +``` + +Como puedes ver la habilidad está en un formato de cadena. Utilicemos JSON.parse() para convertirlo en un array normal. + +```js +let skills = localStorage.getItem("skills"); +let skillsObj = JSON.parse(skills, undefined, 4); +console.log(skillsObj); +``` + +```sh +['HTML','CSS','JS','React'] +``` + +### Limpiando el localStorage + +El método clear, borrará todo lo almacenado en la memoria local + +```js +localStorage.clear(); +``` + +🌕 Estás decidido. Ahora, conociste un Web Storages y supiste cómo almacenar pequeños datos en los navegadores de los clientes. Llevas 17 pasos de ventaja en tu camino hacia la grandeza. Ahora haz algunos ejercicios para tu cerebro y para tu músculo. + +## Ejercicios + +### Ejercicios: Nivel 1 + +1. Guarda tu nombre, apellido, edad, país y ciudad en tu navegador localStorage. + +### Ejercicios: Nivel 2 + +1. Cree un objeto estudiante. El objeto estudiante tendrá el nombre, el apellido, la edad, las habilidades, el país, las claves inscritas y los valores para las claves. Almacena el objeto estudiante en el localStorage de tu navegador. + +### Ejercicios: Nivel 3 + +1. Crear un objeto llamado personAccount. Tiene propiedades de nombre, apellido, ingresos, gastos y tiene métodos 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 y su descripción. + +🎉 ¡FELICITACIONES! 🎉 + +[<< Día 16](../dia_16_JSON/dia_16_json.md) | [Día 18 >>](..)