Repository: mouredev/hello-javascript Branch: main Commit: cd821849becd Files: 62 Total size: 94.5 KB Directory structure: gitextract_r2i1kl2h/ ├── .gitignore ├── .vscode/ │ └── launch.json ├── Basic/ │ ├── 00-helloworld.js │ ├── 01-variables.js │ ├── 02-datatypes.js │ ├── 03-beginner-exercises.js │ ├── 04-operators.js │ ├── 05-operators-exercises.js │ ├── 06-strings.js │ ├── 07-strings-exercises.js │ ├── 08-conditionals.js │ ├── 09-conditionals-exercises.js │ ├── 10-array.js │ ├── 11-set.js │ ├── 12-map.js │ ├── 13-structures-exercises.js │ ├── 14-loops.js │ ├── 15-loops-exercises.js │ ├── 16-functions.js │ ├── 17-functions-exercises.js │ ├── 18-objects.js │ ├── 19-objects-exercises.js │ ├── 20-destructuring-spreading.js │ ├── 21-destructuring-spreading-exercises.js │ ├── 22-classes.js │ ├── 23-classes-exercises.js │ ├── 24-error-handling.js │ ├── 25-error-handling-exercises.js │ ├── 26-console-methods.js │ ├── 27-console-methods-exercises.js │ ├── 28-export-modules.js │ ├── 29-import-modules.js │ ├── 30-import-external-modules.cjs │ ├── 31-modules-exercises.js │ └── package.json ├── Intermediate/ │ ├── 00-advanced-functions.js │ ├── 01-advanced-functions-exercises.js │ ├── 02-advanced-structures.js │ ├── 03-advanced-structures-exercises.js │ ├── 04-advanced-objects.js │ ├── 05-advanced-classes.js │ ├── 06-advanced-objects-classes-exercises.js │ ├── 07-async.js │ ├── 08-async-exercises.js │ ├── 09-apis.js │ ├── 10-apis-exercises.js │ ├── 11-dom.js │ ├── 12-dom-example.html │ ├── 13-dom-example.js │ ├── 14-tasklist.html │ ├── 15-tasklist.js │ ├── 16-dom-exercises.js │ ├── 17-debugging.js │ ├── 18-debugging-exercises.js │ ├── 19-regex.js │ ├── 20-regex-exercises.js │ ├── 21-testing.js │ ├── 22-testing.test.js │ └── 23-testing-exercises.js ├── LICENSE ├── README.md └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules/ ================================================ FILE: .vscode/launch.json ================================================ { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": [ "/**" ], "program": "${workspaceFolder}/Intermediate/17-debugging.js" } ] } ================================================ FILE: Basic/00-helloworld.js ================================================ /* Clases 1 a 14 (sin código) Vídeo: https://youtu.be/1glVfFxj8a4 Clase 15 - Hola mundo Vídeo: https://youtu.be/1glVfFxj8a4?t=2390 */ // Esto es un comentario simple /* Esto es un comentario en varias líneas */ console.log("¡Hola, JavaScript!") console.log('¡Hola, JavaScript!') console.log(`¡Hola, JavaScript!`) // console.log("¡Hola, JavaScript!") /* console.log("¡Hola, JavaScript!") console.log('¡Hola, JavaScript!') console.log(`¡Hola, JavaScript!`) */ console.log("5") console.log(5) console.log(5 + 2) console.log(5 - 2) console.log(5 * 2) console.log(5 / 2) console.log(5 % 2) console.log(5 ** 2) ================================================ FILE: Basic/01-variables.js ================================================ /* Clase 16 - Variables Vídeo: https://youtu.be/1glVfFxj8a4?t=3049 */ // var var helloWorld = "¡Hola, JavaScript!" console.log(helloWorld) helloWorld = "¡Hola de nuevo, JavaScript!" console.log(helloWorld) // let let helloWorld2 = "¡Hola, JavaScript 2!" console.log(helloWorld2) helloWorld2 = "¡Hola de nuevo, JavaScript 2!" console.log(helloWorld2) // const const helloWorld3 = "¡Hola, JavaScript 3!" console.log(helloWorld3) // Error // helloWorld3 = "¡Hola de nuevo, JavaScript 2!" // console.log(helloWorld3) ================================================ FILE: Basic/02-datatypes.js ================================================ /* Clase 17 - Tipos de datos Vídeo: https://youtu.be/1glVfFxj8a4?t=3599 */ // Tipos de datos primitivos // Cadenas de texto (string) let myName = "Brais Moure" let alias = 'MoureDev' let email = `braismoure@mouredev.com` // Números (number) let age = 37 // Entero let height = 1.77 // Decimal // Booleanos (boolean) let isTeacher = true let isStudent = false // Undefined let undefinedValue console.log(undefinedValue) // Null let nullValue = null // Symbol let mySymbol = Symbol("mysymbol") // BigInt let myBigInt = BigInt(817239871289371986589716389471628379612983761289376129) let myBigInt2 = 817239871289371986589716389471628379612983761289376129n // Mostramos los tipos de datos console.log(typeof myName) console.log(typeof alias) console.log(typeof email) console.log(typeof age) console.log(typeof height) console.log(typeof isTeacher) console.log(typeof isStudent) console.log(typeof undefinedValue) console.log(typeof nullValue) console.log(typeof mySymbol) console.log(typeof myBigInt) console.log(typeof myBigInt2) ================================================ FILE: Basic/03-beginner-exercises.js ================================================ /* Clase 18 - Ejercicios: primeros pasos Vídeo: https://youtu.be/1glVfFxj8a4?t=4733 */ // 1. Escribe un comentario en una línea // 2. Escribe un comentario en varias líneas // 3. Declara variables con valores asociados a todos los datos de tipo primitivos // 4. Imprime por consola el valor de todas las variables // 5. Imprime por consola el tipo de todas las variables // 6. A continuación, modifica los valores de las variables por otros del mismo tipo // 7. A continuación, modifica los valores de las variables por otros de distinto tipo // 8. Declara constantes con valores asociados a todos los tipos de datos primitivos // 9. A continuación, modifica los valores de las constantes // 10. Comenta las líneas que produzcan algún tipo de error al ejecutarse ================================================ FILE: Basic/04-operators.js ================================================ /* Clase 19 - Operadores Vídeo: https://youtu.be/1glVfFxj8a4?t=4937 */ // Operadores Aritméticos let a = 5 let b = 10 console.log(a + b) // Suma console.log(a - b) // Resta console.log(a * b) // Multiplicación console.log(a / b) // División console.log(a % b) // Módulo console.log(a ** b) // Exponente a++ // Incremento console.log(a) b-- // Decremento console.log(b) // Operadores de asignacion let myVariable = 2 console.log(myVariable) myVariable += 2 // Suma con asignación console.log(myVariable) myVariable -= 2 // Resta con asignación myVariable *= 2 // Multiplicación con asignación myVariable /= 2 // División con asignación myVariable %= 2 // Módulo con asignación myVariable **= 2 // Exponente con asignación // Operadores de comparación console.log(a > b) // Mayor que console.log(a < b) // Menor que console.log(a >= b) // Mayor o igual que console.log(a <= b) // Menor o igual que console.log(a == b) // Igualdad por valor console.log(a == 6) console.log(a == "6") console.log(a == a) console.log(a === a) // Igualdad por identidad (por tipo y valor) o igualdad estricta console.log(a === 6) console.log(a === "6") console.log(a != 6) // Desigualdad por valor console.log(a !== "6") // Desigualdad por identidad (por tipo y valor) o desigualdad estricta console.log(0 == false) console.log(1 == false) console.log(2 == false) console.log(0 == "") console.log(0 == " ") console.log(0 == '') console.log(0 == "Hola") console.log(0 === "") console.log(undefined == null) console.log(undefined === null) /* Truthy values (valores verdaderos) - Todos los numeros positivos y negativos menos el cero - Todas las cadenas de texto menos las vacías - El boolean true */ /* Falsy values (valores falsos) - 0 - 0n - null - undefined - NaN (Not a Number) - El boolean false - Cadenas de texto vacías */ // Operadores lógicos // and (&&) console.log(5 > 10 && 15 > 20) console.log(5 < 10 && 15 < 20) console.log(5 < 10 && 15 > 20) console.log(5 > 10 && 15 > 20 && 30 > 40) // or (||) console.log(5 > 10 || 15 > 20) console.log(5 < 10 || 15 < 20) console.log(5 < 10 || 15 > 20) console.log(5 > 10 || 15 > 20 || 30 > 40) console.log(5 > 10 && 15 > 20 || 30 < 40) // not (!) console.log(!true) console.log(!false) console.log(!(5 > 10 && 15 > 20)) console.log(!(5 > 10 || 15 > 20)) // Operadores ternarios const isRaining = false isRaining ? console.log("Está lloviendo") : console.log("No está lloviendo") ================================================ FILE: Basic/05-operators-exercises.js ================================================ /* Clase 20 - Ejercicios: Operadores Vídeo: https://youtu.be/1glVfFxj8a4?t=6458 */ // 1. Crea una variable para cada operación aritmética // 2. Crea una variable para cada tipo de operación de asignación, // que haga uso de las variables utilizadas para las operaciones aritméticas // 3. Imprime 5 comparaciones verdaderas con diferentes operadores de comparación // 4. Imprime 5 comparaciones falsas con diferentes operadores de comparación // 5. Utiliza el operador lógico and // 6. Utiliza el operador lógico or // 7. Combina ambos operadores lógicos // 8. Añade alguna negación // 9. Utiliza el operador ternario // 10. Combina operadores aritméticos, de comparáción y lógicas ================================================ FILE: Basic/06-strings.js ================================================ /* Clase 21 - Strings Vídeo: https://youtu.be/1glVfFxj8a4?t=6565 */ // Strings (cadenas de texto) // Concatenación let myName = "Brais" let greeting = "Hola, " + myName + "!" console.log(greeting) console.log(typeof greeting) // Longitud console.log(greeting.length) // Acceso a caracteres console.log(greeting[0]) console.log(greeting[11]) // Métodos comunes console.log(greeting.toUpperCase()) // Mayúsculas console.log(greeting.toLowerCase()) // Minúsculas console.log(greeting.indexOf("Hola")) // Índice console.log(greeting.indexOf("Brais")) console.log(greeting.indexOf("MoureDev")) console.log(greeting.includes("Hola")) // Incluye console.log(greeting.includes("Brais")) console.log(greeting.includes("MoureDev")) console.log(greeting.slice(0, 10)) // Sección console.log(greeting.replace("Brais", "MoureDev")) // Reemplazo // Template literals (plantillas literales) // Strings en varias líneas let message = `Hola, este es mi curso de JavaScript` console.log(message) // Interpolación de valores let email = "braismoure@mouredev.com" console.log(`Hola, ${myName}! Tu email es ${email}.`) ================================================ FILE: Basic/07-strings-exercises.js ================================================ /* Clase 22 - Ejercicios: Strings Vídeo: https://youtu.be/1glVfFxj8a4?t=7226 */ // 1. Concatena dos cadenas de texto // 2. Muestra la longitud de una cadena de texto // 3. Muestra el primer y último carácter de un string // 4. Convierte a mayúsculas y minúsculas un string // 5. Crea una cadena de texto en varias líneas // 6. Interpola el valor de una variable en un string // 7. Reemplaza todos los espacios en blanco de un string por guiones // 8. Comprueba si una cadena de texto contiene una palabra concreta // 9. Comprueba si dos strings son iguales // 10. Comprueba si dos strings tienen la misma longitud ================================================ FILE: Basic/08-conditionals.js ================================================ /* Clase 23 - Condicionales Vídeo: https://youtu.be/1glVfFxj8a4?t=7277 */ // if, else if, else // if (si) let age = 37 if (age == 37) { console.log("La edad es 37") } // else (si no) if (age == 37) { console.log("La edad es 37") } else { console.log("La edad no es 37") } // else if (si no, si) if (age == 37) { console.log("La edad es 37") } else if (age < 18) { console.log("Es menor de edad") } else { console.log("La edad no es 37 ni es menor de edad") } // Operador ternario const message = age == 37 ? "La edad es 37" : "La edad no es 37" console.log(message) // switch let day = 3 let dayName switch (day) { case 0: dayName = "Lunes" break case 1: dayName = "Martes" break case 2: dayName = "Miércoles" break case 3: dayName = "Jueves" break case 4: dayName = "Viernes" break case 5: dayName = "Sábado" break case 6: dayName = "Domingo" break default: dayName = "Número de día incorrecto" } console.log(dayName) ================================================ FILE: Basic/09-conditionals-exercises.js ================================================ /* Clase 24 - Ejercicios: Condicionales Vídeo: https://youtu.be/1glVfFxj8a4?t=8652 */ // if/else/else if/ternaria // 1. Imprime por consola tu nombre si una variable toma su valor // 2. Imprime por consola un mensaje si el usuario y contraseña concide con unos establecidos // 3. Verifica si un número es positivo, negativo o cero e imprime un mensaje // 4. Verifica si una persona puede votar o no (mayor o igual a 18) e indica cuántos años le faltan // 5. Usa el operador ternario para asignar el valor "adulto" o "menor" a una variable // dependiendo de la edad // 6. Muestra en que estación del año nos encontramos dependiendo del valor de una variable "mes" // 7. Muestra el número de días que tiene un mes dependiendo de la variable del ejercicio anterior // switch // 8. Usa un switch para imprimir un mensaje de saludo diferente dependiendo del idioma // 9. Usa un switch para hacer de nuevo el ejercicio 6 // 10. Usa un switch para hacer de nuevo el ejercicio 7 ================================================ FILE: Basic/10-array.js ================================================ /* Clase 25 - Arrays Vídeo: https://youtu.be/1glVfFxj8a4?t=8741 */ // Array // Declaración let myArray = [] let myArray2 = new Array() console.log(myArray) console.log(myArray2) // Inicialización myArray = [3] myArray2 = new Array(3) console.log(myArray) console.log(myArray2) myArray = [1, 2, 3, 4] myArray2 = new Array(1, 2, 3, 4) console.log(myArray) console.log(myArray2) myArray = ["Brais", "Moure", "mouredev", 37, true] myArray2 = new Array("Brais", "Moure", "mouredev", 37, true) console.log(myArray) console.log(myArray2) myArray2 = new Array(3) myArray2[2] = "Brais" // myArray2[0] = "Moure" myArray2[1] = "mouredev" myArray2[4] = "mouredev" console.log(myArray2) myArray = [] myArray[2] = "Brais" // myArray[0] = "Moure" myArray[1] = "mouredev" console.log(myArray) // Métodos comunes myArray = [] // push y pop myArray.push("Brais") myArray.push("Moure") myArray.push("mouredev") myArray.push(37) console.log(myArray) console.log(myArray.pop()) // Elimina el último y lo devuelve myArray.pop() console.log(myArray) // shift y unshift console.log(myArray.shift()) console.log(myArray) myArray.unshift("Brais", "mouredev") console.log(myArray) // length console.log(myArray.length) // clear myArray = [] myArray.length = 0 // alternativa console.log(myArray) // slice myArray = ["Brais", "Moure", "mouredev", 37, true] let myNewArray = myArray.slice(1, 3) console.log(myArray) console.log(myNewArray) // splice myArray.splice(1, 3) console.log(myArray) myArray = ["Brais", "Moure", "mouredev", 37, true] myArray.splice(1, 2, "Nueva entrada") console.log(myArray) ================================================ FILE: Basic/11-set.js ================================================ /* Clase 26 - Sets Vídeo: https://youtu.be/1glVfFxj8a4?t=9952 */ // Set // Declaración let mySet = new Set() console.log(mySet) // Inicialización mySet = new Set(["Brais", "Moure", "mouredev", 37, true, "braismoure@mouredev.com"]) console.log(mySet) // Métodos comunes // add y delete mySet.add("https://moure.dev") console.log(mySet) mySet.delete("https://moure.dev") console.log(mySet) console.log(mySet.delete("Brais")) console.log(mySet.delete(4)) console.log(mySet) // has console.log(mySet.has("Moure")) console.log(mySet.has("Brais")) // size console.log(mySet.size) // Convertir un set a array let myArray = Array.from(mySet) console.log(myArray) // Convertir un array a set mySet = new Set(myArray) console.log(mySet) // No admite duplicados mySet.add("braismoure@mouredev.com") mySet.add("braismoure@mouredev.com") mySet.add("braismoure@mouredev.com") mySet.add("BraisMoure@mouredev.com") console.log(mySet) ================================================ FILE: Basic/12-map.js ================================================ /* Clase 27 - Maps Vídeo: https://youtu.be/1glVfFxj8a4?t=10755 */ // Map // Declaración let myMap = new Map() console.log(myMap) // Inicialiación myMap = new Map([ ["name", "Brais"], ["email", "braismoure@mouredev.com"], ["age", 37] ]) console.log(myMap) // Métodos y propiedades // set myMap.set("alias", "mouredev") myMap.set("name", "Brais Moure") console.log(myMap) // get console.log(myMap.get("name")) console.log(myMap.get("surname")) // has console.log(myMap.has("surname")) console.log(myMap.has("age")) // delete myMap.delete("email") console.log(myMap) // keys, values y entries console.log(myMap.keys()) console.log(myMap.values()) console.log(myMap.entries()) // size console.log(myMap.size) // clear myMap.clear() console.log(myMap) ================================================ FILE: Basic/13-structures-exercises.js ================================================ /* Clase 28 - Ejercicios: Estructuras Vídeo: https://youtu.be/1glVfFxj8a4?t=11451 */ // 1. Crea un array que almacene cinco animales // 2. Añade dos más. Uno al principio y otro al final // 3. Elimina el que se encuentra en tercera posición // 4. Crea un set que almacene cinco libros // 5. Añade dos más. Uno de ellos repetido // 6. Elimina uno concreto a tu elección // 7. Crea un mapa que asocie el número del mes a su nombre // 8. Comprueba si el mes número 5 existe en el map e imprime su valor // 9. Añade al mapa una clave con un array que almacene los meses de verano // 10. Crea un Array, transfórmalo a un Set y almacénalo en un Map ================================================ FILE: Basic/14-loops.js ================================================ /* Clase 29 - Bucles Vídeo: https://youtu.be/1glVfFxj8a4?t=11575 */ // Loops o bucles // for for (let i = 0; i < 5; i++) { console.log(`Hola ${i}`) } const numbers = [1, 2, 3, 4, 5, 6, 7, 8] for (let i = 0; i < numbers.length; i++) { console.log(`Elemento: ${numbers[i]}`) } // while let i = 0 while (i < 5) { console.log(`Hola ${i}`) i++ } // Bucle infinito // while(true) { // } // do while i = 6 do { console.log(`Hola ${i}`) i++ } while (i < 5) // for of const myArray = [1, 2, 3, 4] const mySet = new Set(["Brais", "Moure", "mouredev", 37, true, "braismoure@mouredev.com"]) const myMap = new Map([ ["name", "Brais"], ["email", "braismoure@mouredev.com"], ["age", 37] ]) const myString = "¡Hola, JavaScript!" for (let value of myArray) { console.log(value) } for (let value of mySet) { console.log(value) } for (let value of myMap) { console.log(value) } for (let value of myString) { console.log(value) } // break y continue for (let i = 0; i < 10; i++) { if (i == 5) { continue } else if (i == 7) { break } console.log(`Hola ${i}`) } ================================================ FILE: Basic/15-loops-exercises.js ================================================ /* Clase 30 - Ejercicios: Bucles Vídeo: https://youtu.be/1glVfFxj8a4?t=12732 */ // NOTA: Explora diferentes sintaxis de bucles para resolver los ejercicios // 1. Crea un bucle que imprima los números del 1 al 20 // 2. Crea un bucle que sume todos los números del 1 al 100 y muestre el resultado // 3. Crea un bucle que imprima todos los números pares entre 1 y 50 // 4. Dado un array de nombres, usa un bucle para imprimir cada nombre en la consola // 5. Escribe un bucle que cuente el número de vocales en una cadena de texto // 6. Dado un array de números, usa un bucle para multiplicar todos los números y mostrar el producto // 7. Escribe un bucle que imprima la tabla de multiplicar del 5 // 8. Usa un bucle para invertir una cadena de texto // 9. Usa un bucle para generar los primeros 10 números de la secuencia de Fibonacci // 10. Dado un array de números, usa un bucle para crear un nuevo array que contenga solo los números mayores a 10 ================================================ FILE: Basic/16-functions.js ================================================ /* Clase 31 - Funciones Vídeo: https://youtu.be/1glVfFxj8a4?t=12829 */ // Funciones // Simple function myFunc() { console.log("¡Hola, función!") } for (let i = 0; i < 5; i++) { myFunc() } // Con parámetros function myFuncWithParams(name) { console.log(`¡Hola, ${name}!`) } myFuncWithParams("Brais") myFuncWithParams("MoureDev") // Funciones anónimas const myFunc2 = function (name) { console.log(`¡Hola, ${name}!`) } myFunc2("Brais Moure") // Arrow functions const myFunc3 = (name) => { console.log(`¡Hola, ${name}!`) } const myFunc4 = (name) => console.log(`¡Hola, ${name}!`) myFunc3("Brais Moure") myFunc4("Brais Moure") // Parámetros function sum(a, b) { console.log(a + b) } sum(5, 10) sum(5) sum() function defaultSum(a = 0, b = 0) { console.log(a + b) } // Por defecto defaultSum() defaultSum(5) defaultSum(5, 10) defaultSum(undefined, 5) // Retorno de valores function mult(a, b) { return a * b } let result = mult(5, 10) console.log(result) // Funciones anidadas function extern() { console.log("Función externa") function intern() { console.log("Función interna") } intern() } extern() // intern() Error: fuera del scope // Funciones de orden superior function applyFunc(func, param) { func(param) } applyFunc(myFunc4, "función de orden superior") // forEach const myArray = [1, 2, 3, 4] const mySet = new Set(["Brais", "Moure", "mouredev", 37, true, "braismoure@mouredev.com"]) const myMap = new Map([ ["name", "Brais"], ["email", "braismoure@mouredev.com"], ["age", 37] ]) myArray.forEach(function (value) { console.log(value) }) myArray.forEach((value) => console.log(value)) mySet.forEach((value) => console.log(value)) myMap.forEach((value) => console.log(value)) ================================================ FILE: Basic/17-functions-exercises.js ================================================ /* Clase 32 - Ejercicios: Funciones Vídeo: https://youtu.be/1glVfFxj8a4?t=14146 */ // NOTA: Explora diferentes sintaxis de funciones para resolver los ejercicios // 1. Crea una función que reciba dos números y devuelva su suma // 2. Crea una función que reciba un array de números y devuelva el mayor de ellos // 3. Crea una función que reciba un string y devuelva el número de vocales que contiene // 4. Crea una función que reciba un array de strings y devuelva un nuevo array con las strings en mayúsculas // 5. Crea una función que reciba un número y devuelva true si es primo, y false en caso contrario // 6. Crea una función que reciba dos arrays y devuelva un nuevo array que contenga los elementos comunes entre ambos // 7. Crea una función que reciba un array de números y devuelva la suma de todos los números pares // 8. Crea una función que reciba un array de números y devuelva un nuevo array con cada número elevado al cuadrado // 9. Crea una función que reciba una cadena de texto y devuelva la misma cadena con las palabras en orden inverso // 10. Crea una función que calcule el factorial de un número dado ================================================ FILE: Basic/18-objects.js ================================================ /* Clase 33 - Objetos Vídeo: https://youtu.be/1glVfFxj8a4?t=14229 */ // Objetos // Sintaxis let person = { name: "Brais", age: 37, alias: "MoureDev" } // Acceso a propiedades // Notación punto console.log(person.name) // Notación de corchetes console.log(person["name"]) // Modificación de propiedades person.name = "Brais Moure" console.log(person.name) console.log(typeof person.age) person.age = "37" console.log(person.age) console.log(typeof person.age) // Eliminación de propiedades delete person.age console.log(person) // Nueva propiedad person.email = "braismoure@mouredev.com" person["age"] = 37 console.log(person) // Métodos (funciones) let person2 = { name: "Brais", age: 37, alias: "MoureDev", walk: function () { console.log("La persona camina.") } } person2.walk() // Anidación de objetos let person3 = { name: "Brais", age: 37, alias: "MoureDev", walk: function () { console.log("La persona camina.") }, job: { name: "Programador", exp: 15, work: function () { console.log(`La persona de ${this.age} años de experiencia trabaja.`) } } } console.log(person3) console.log(person3.name) console.log(person3.job) console.log(person3.job.name) person3.job.work() // Igualdad de objetos let person4 = { name: "Brais Moure", alias: "MoureDev", email: "braismoure@mouredev.com", age: 37 } console.log(person) console.log(person4) console.log(person == person4) console.log(person === person4) console.log(person.name == person4.name) // Iteración for (let key in person4) { console.log(key + ": " + person4[key]) } // Funciones como objetos function Person(name, age) { // Debería ser una clase this.name = name this.age = age } let person5 = new Person("Brais", 37) console.log(person5) console.log(person5.name) console.log(typeof person5) console.log(typeof person4) ================================================ FILE: Basic/19-objects-exercises.js ================================================ /* Clase 34 - Ejercicios: Objetos Vídeo: https://youtu.be/1glVfFxj8a4?t=15675 */ // 1. Crea un objeto con 3 propiedades // 2. Accede y muestra su valor // 3. Agrega una nueva propiedad // 4. Elimina una de las 3 primeras propiedades // 5. Agrega una función e invócala // 6. Itera las propiedades del objeto // 7. Crea un objeto anidado // 8. Accede y muestra el valor de las propiedades anidadas // 9. Comprueba si los dos objetos creados son iguales // 10. Comprueba si dos propiedades diferentes son iguales ================================================ FILE: Basic/20-destructuring-spreading.js ================================================ /* Clase 35 - Desestructuración y propagación Vídeo: https://youtu.be/1glVfFxj8a4?t=15747 */ let myArray = [1, 2, 3, 4] let person = { name: "Brais", age: 37, alias: "MoureDev" } let myValue = myArray[1] console.log(myValue) let myName = person.name console.log(myName) // Desestructuración // Sintaxis arrays let [myValue0, myValue1, myValue2, myValue3, myValue4] = myArray console.log(myValue0) console.log(myValue1) console.log(myValue2) console.log(myValue3) console.log(myValue4) // Sintaxis arrays con valores predeterminados let [myValue5 = 0, myValue6 = 0, myValue7 = 0, myValue8 = 0, myValue9 = 0] = myArray console.log(myValue5) console.log(myValue6) console.log(myValue7) console.log(myValue8) console.log(myValue9) // Ignorar elementos array let [myValue10, , , myValue13] = myArray console.log(myValue10) console.log(myValue13) // Sintaxis objects let { name, age, alias } = person console.log(name) console.log(age) console.log(alias) // Sintaxis objects con valores predeterminados let { name2, age2, alias2, email = "email@email.com" } = person console.log(name2) // No existe console.log(age2) // No existe console.log(alias2) // No existe console.log(email) // Sintaxis objects con nuevos nombres de variables let { alias: alias3, name: name3, age: age3 } = person console.log(name3) console.log(age3) console.log(alias3) // Objects anidados let person3 = { name: "Brais", age: 37, alias: "MoureDev", walk: function () { console.log("La persona camina.") }, job: { name: "Programador", exp: 15, work: function () { console.log(`La persona de ${this.age} años de experiencia trabaja.`) } } } let { name: name4, job: { name: jobName } } = person3 console.log(name4) console.log(jobName) // Propagación (...) // Sintaxis arrays let myArray2 = [...myArray, 5, 6] console.log(myArray2) // Copia de arrays let myArray3 = [...myArray] console.log(myArray3) // Combinación de arrays let myArray4 = [...myArray, ...myArray2, ...myArray3] console.log(myArray4) // Sintaxis objects let person4 = { ...person, email: "braismoure@mouredev.com" } console.log(person4) // Copia de objects let person5 = { ...person } console.log(person5) ================================================ FILE: Basic/21-destructuring-spreading-exercises.js ================================================ /* Clase 36 - Ejercicios: Desestructuración y propagación Vídeo: https://youtu.be/1glVfFxj8a4?t=16802 */ // 1. Usa desestructuración para extraer los dos primeros elementos de un array // 2. Usa desestructuración en un array y asigna un valor predeterminado a una variable // 3. Usa desestructuración para extraer dos propiedades de un objeto // 4. Usa desestructuración para extraer dos propiedades de un objeto y asígnalas // a nuevas variables con nombres diferentes // 5. Usa desestructuración para extraer dos propiedades de un objeto anidado // 6. Usa propagación para combinar dos arrays en uno nuevo // 7. Usa propagación para crear una copia de un array // 8. Usa propagación para combinar dos objetos en uno nuevo // 9. Usa propagación para crear una copia de un objeto // 10. Combina desestructuración y propagación ================================================ FILE: Basic/22-classes.js ================================================ /* Clase 37 - Clases Vídeo: https://youtu.be/1glVfFxj8a4?t=16864 */ // Clases class Person { constructor(name, age, alias) { this.name = name this.age = age this.alias = alias } } // Sintaxis let person = new Person("Brais", 37, "MoureDev") let person2 = new Person("Brais", 37, "MoureDev") console.log(person) console.log(person2) console.log(typeof person) // Valores por defecto class DefaultPerson { constructor(name = "Sin nombre", age = 0, alias = "Sin alias") { this.name = name this.age = age this.alias = alias } } let person3 = new DefaultPerson("Brais", 37) console.log(person3) // Acceso a propiedades console.log(person3.alias) console.log(person3["alias"]) person3.alias = "MoureDev" console.log(person3.alias) // Funciones en clases class PersonWithMethod { constructor(name, age, alias) { this.name = name this.age = age this.alias = alias } walk() { console.log("La persona camina.") } } let person4 = new PersonWithMethod("Brais", 37, "MoureDev") person4.walk() // Propiedades privadas class PrivatePerson { #bank constructor(name, age, alias, bank) { this.name = name this.age = age this.alias = alias this.#bank = bank } pay() { this.#bank } } let person5 = new PrivatePerson("Brais", 37, "MoureDev", "IBAN123456789") // No podemos acceder // console.log(person5.bank) // person5.bank = "new IBAN123456789" // bank no es #bank console.log(person5) // Getters y Setters class GetSetPerson { #name #age #alias #bank constructor(name, age, alias, bank) { this.#name = name this.#age = age this.#alias = alias this.#bank = bank } get name() { return this.#name } set bank(bank) { this.#bank = bank } } person6 = new GetSetPerson("Brais", 37, "MoureDev", "IBAN123456789") console.log(person6) console.log(person6.name) person6.bank = "new IBAN123456789" /* Clase 38 - Herencia de clases Vídeo: https://youtu.be/1glVfFxj8a4?t=17999 */ // Herencia class Animal { constructor(name) { this.name = name } sound() { console.log("El animal emite un sonido genérico") } } class Dog extends Animal { sound() { console.log("Guau!") } run() { console.log("El perro corre") } } class Fish extends Animal { constructor(name, size) { super(name) this.size = size } swim() { console.log("El pez nada") } } let myDog = new Dog("MoureDog") myDog.run() myDog.sound() let myFish = new Fish("MoureFish", 10) myFish.swim() myFish.sound() // Métodos estáticos class MathOperations { static sum(a, b) { return a + b } } console.log(MathOperations.sum(5, 10)) ================================================ FILE: Basic/23-classes-exercises.js ================================================ /* Clase 39 - Ejercicios: Clases Vídeo: https://youtu.be/1glVfFxj8a4?t=18630 */ // 1. Crea una clase que reciba dos propiedades // 2. Añade un método a la clase que utilice las propiedades // 3. Muestra los valores de las propiedades e invoca a la función // 4. Añade un método estático a la primera clase // 5. Haz uso del método estático // 6. Crea una clase que haga uso de herencia // 7. Crea una clase que haga uso de getters y setters // 8. Modifica la clase con getters y setters para que use propiedades privadas // 9. Utiliza los get y set y muestra sus valores // 10. Sobrescribe un método de una clase que utilice herencia ================================================ FILE: Basic/24-error-handling.js ================================================ /* Clase 40 - Manejo de errores Vídeo: https://youtu.be/1glVfFxj8a4?t=18751 */ // Excepción // Produce una excepción let myObject // console.log(myObject.email) // Captura de errores // try-catch try { // Código que intenta ejecutar console.log(myObject.email) console.log("Finaliza la ejecución sin errores") } catch { // Bloque de error console.log("Se ha producido un error") } // Captura del error try { console.log(myObject.email) } catch (error) { console.log("Se ha producido un error:", error.message) } // finally try { console.log(myObject.email) } catch (error) { console.log("Se ha producido un error:", error.message) } finally { console.log("Este código se ejecuta siempre") } // No está soportado // try { // console.log(myObject.email) // } finally { // console.log("Este código se ejecuta siempre") // } // Lanzamiento de errores // throw // throw new Error("Se ha producido un error") function sumIntegers(a, b) { if (typeof a !== "number" || typeof b !== "number") { throw new TypeError("Esta operación sólo suma números") } if (!Number.isInteger(a) || !Number.isInteger(b)) { throw new Error("Esta operación sólo suma números enteros") } if (a == 0 || b == 0) { throw new SumZeroIntegerError("Se está intentando sumar cero", a, b) } return a + b } try { console.log(sumIntegers(5, 10)) // console.log(sumIntegers(5.5, 10)) console.log(sumIntegers("5", 10)) // console.log(sumIntegers(5, "10")) // console.log(sumIntegers("5", "10")) } catch (error) { console.log("Se ha producido un error:", error.message) } // Capturar varios tipos de errores try { // console.log(sumIntegers(5.5, 10)) console.log(sumIntegers("5", 10)) } catch (error) { if (error instanceof TypeError) { console.log("Se ha producido un error de tipo:", error.message) } else if (error instanceof Error) { console.log("Se ha producido un error:", error.message) } } // Crear excepciones personalizadas class SumZeroIntegerError extends Error { constructor(message, a, b) { super(message) this.a = a this.b = b } printNumbers() { console.log(this.a, " + ", this.b) } } try { console.log(sumIntegers(0, 10)) } catch (error) { console.log("Se ha producido un error personalizado:", error.message) error.printNumbers() } ================================================ FILE: Basic/25-error-handling-exercises.js ================================================ /* Clase 41 - Ejercicios: Manejo de errores Vídeo: https://youtu.be/1glVfFxj8a4?t=20392 */ // 1. Captura una excepción utilizando try-catch // 2. Captura una excepción utilizando try-catch y finally // 3. Lanza una excepción genérica // 4. Crea una excepción personalizada // 5. Lanza una excepción personalizada // 6. Lanza varias excepciones según una lógica definida // 7. Captura varias excepciones en un mismo try-catch // 8. Crea un bucle que intente transformar a float cada valor y capture y muestre los errores // 9. Crea una función que verifique si un objeto tiene una propiedad específica y lance una excepción personalizada // 10. Crea una función que realice reintentos en caso de error hasta un máximo de 10 ================================================ FILE: Basic/26-console-methods.js ================================================ /* Clase 42 - Console Vídeo: https://youtu.be/1glVfFxj8a4?t=20444 */ // Console // log console.log("¡Hola, JavaScript!") // error console.error("Este es un mensaje de error.") console.error("Error al conectarse a la base de datos: ", new Error("Conexión fallida.")) // warn console.warn("Este es un mensaje de advertencia.") // info console.info("Este es un mensaje de información adicional.") // table let data = [ ["Brais", 37], ["Sara", 21] ] console.table(data) data = [ { name: "Brais", age: 37 }, { name: "Sara", age: 21 } ] console.table(data) // group console.group("Usuario:") console.log("Nombre: Brais") console.log("Edad: 37") console.groupEnd() // time console.time("Tiempo de ejecución 2") for (let i = 0; i < 10000; i++) { } console.time("Tiempo de ejecución 1") for (let i = 0; i < 10000; i++) { } console.timeEnd("Tiempo de ejecución 2") for (let i = 0; i < 10000; i++) { } console.timeEnd("Tiempo de ejecución 1") // assert let age = 17 console.assert(age >= 18, "El usuario debe ser mayor de edad.") // count console.count("Click") console.count("Click") console.count("Click") console.countReset("Click") console.count("Click") // trace function funcA() { funcB() } function funcB() { console.trace("Seguimiento de la ejecución.") } funcA() // clear // console.clear() ================================================ FILE: Basic/27-console-methods-exercises.js ================================================ /* Clase 43 - Ejercicios: Console Vídeo: https://youtu.be/1glVfFxj8a4?t=21421 */ // 1. Crea un función que utilice error correctamente // 2. Crea una función que utilice warn correctamente // 3. Crea una función que utilice info correctamente // 4. Utiliza table // 5. Utiliza group // 6. Utiliza time // 7. Valida con assert si un número es positivo // 8. Utiliza count // 9. Utiliza trace // 10. Utiliza clear ================================================ FILE: Basic/28-export-modules.js ================================================ /* Clase 44 - Módulos Vídeo: https://youtu.be/1glVfFxj8a4?t=21480 */ // Exportación de módulos // Funciones export function add(a, b) { return a + b } console.log(add(5, 10)) // Propiedades export const PI = 3.1416 export let name = "MoureDev" // Clases export class Circle { constructor(radius) { this.radius = radius } area() { return Math.PI * Math.pow(this.radius, 2) } perimeter() { return 2 * Math.PI * this.radius } } // Exportación por defecto export default function substract(a, b) { return a - b } // export default class MyClass { // func() { // console.log("Mi clase") // } // } ================================================ FILE: Basic/29-import-modules.js ================================================ /* Clase 44 - Módulos Vídeo: https://youtu.be/1glVfFxj8a4?t=21480 */ // Importación de módulos import { add, PI, name, Circle } from "./28-export-modules.js" import defaultImport from "./28-export-modules.js" // Funciones console.log(add(5, 10)) // Propiedades console.log(PI) console.log(name) // Clases let circle = new Circle(10) console.log(circle.radius) console.log(circle.area().toFixed(2)) console.log(circle.perimeter().toFixed(2)) // Importación por defecto console.log(defaultImport(5, 10)) // let myClass = new defaultImport() // myClass.func() // Proyecto modular // import { MyImport } from "./directory/file.js" ================================================ FILE: Basic/30-import-external-modules.cjs ================================================ /* Clase 44 - Módulos Vídeo: https://youtu.be/1glVfFxj8a4?t=21480 */ // Módulos externos const os = require("os") console.log(os.platform()) console.log(os.arch()) console.log(os.totalmem()) console.log(os.freemem()) ================================================ FILE: Basic/31-modules-exercises.js ================================================ /* Clase 45 - Ejercicios: Módulos Vídeo: https://youtu.be/1glVfFxj8a4?t=22720 */ // 1. Exporta una función // 2. Exporta una constante // 3. Exporta una clase // 4. Importa una función // 5. Importa una constante // 6. Importa una clase // 7. Exporta una función, una constante y una clase por defecto (en caso de que lo permita) // 8. Importa una función, una constante y una clase por defecto (en caso de que lo permita) // 9. Exporta una función, una constante y una clase desde una carpeta // 10. Importa una función, una constante y una clase desde un directorio diferente al anterior ================================================ FILE: Basic/package.json ================================================ { "type": "module" } ================================================ FILE: Intermediate/00-advanced-functions.js ================================================ /* Clases 2 a 11 - Funciones avanzadas Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=346 */ // Ciudadanos de primera clase const greet = function (name) { console.log(`Hola, ${name}`) } greet("Brais") function processGreeting(greetFunction, name) { greetFunction(name) } function returnGreeting() { return greet } processGreeting(greet, "MoureDev") const greet2 = returnGreeting() greet2("Brais Moure") // Arrow functions avanzadas // - Retorno implícito const multiply = (a, b) => a * b console.log(multiply(2, 5)) // - this léxico const handler = { name: "Brais", greeting: function () { console.log(`Hola, ${this.name}`) }, arrowGreeting: () => { console.log(`Hola, ${this.name}`) } } handler.greeting() handler.arrowGreeting(); // IIFE (Expresión de Función Invocada Inmediatamente) (function () { console.log("IIFE clásico") })(); (() => { console.log("IIFE con arrow function") })(); // Parámetros Rest (...) function sum(...numbers) { let result = 0 for (let number of numbers) { result += number } return result } console.log(sum(1, 2, 3, 4, 5)) console.log(sum(10, 15)) // Operador Spread (...) const numbers = [1, 2, 3] function sumWithSpread(a, b, c) { return a + b + c } console.log(sumWithSpread(1, 2, 3)) // Sin Spread console.log(sumWithSpread(...numbers)) // Con Spread // Closures (Clausuras) function createCounter() { let counter = 0 return function () { counter++ console.log(`Contador: ${counter}`) } } const counter = createCounter() counter() counter() counter() counter() // Recursividad function factorial(n) { if (n <= 1) { return 1 } return n * factorial(n - 1) } console.log(factorial(5)) // Funciones parciales function partialSum(a) { return function (b, c) { return sum(a, b, c) } } const sumWith = partialSum(4) console.log(sumWith(2, 3)) console.log(sumWith(1, 2)) // Currying function currySum(a) { return function (b) { return function (c) { return function (d) { return sum(a, b, c, d) } } } } const sumAB = currySum(1)(2) const sumC = sumAB(3) console.log(sumC(3)) console.log(sumC(4)) console.log(sumAB(5)(7)) // Callbacks function processData(data, callback) { const result = sum(...data) callback(result) } function processResult(result) { console.log(result) } function processResult2(result) { console.log(`Mi resultado es: ${result}`) } processData([1, 2, 3], processResult) processData([1, 2, 3], processResult2) processData([1, 2, 3], (result) => { console.log(`Mi resultado en la arrow function es: ${result}`) }) ================================================ FILE: Intermediate/01-advanced-functions-exercises.js ================================================ /* Clase 12 - Funciones avanzadas Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=4112 */ // 1. Crea una función que retorne a otra función // 2. Implementa una función currificada que multiplique 3 números // 3. Desarrolla una función recursiva que calcule la potencia de un número elevado a un exponente // 4. Crea una función createCounter() que reciba un valor inicial y retorne un objeto con métodos para increment(), decrement() y getValue(), utilizando un closure para mantener el estado // 5. Crea una función sumManyTimes(multiplier, ...numbers) que primero sume todos los números (usando parámetros Rest) y luego multiplique el resultado por multiplier // 6. Crea un Callback que se invoque con el resultado de la suma de todos los números que se le pasan a una función // 7. Desarrolla una función parcial // 8. Implementa un ejemplo que haga uso de Spread // 9. Implementa un retorno implícito // 10. Haz uso del this léxico ================================================ FILE: Intermediate/02-advanced-structures.js ================================================ /* Clases 13 a 22 - Estructuras avanzadas Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=4355 */ // Arrays avanzados // - Métodos funcionales // forEach let numbers = [1, 2, 3, 4, 5, 6] numbers.forEach(element => console.log(element)) // map let doubled = numbers.map(element => element * 2) console.log(doubled) // filter let evens = numbers.filter(element => element % 2 === 0) console.log(evens) // reduce let sum = numbers.reduce((result, current) => result + current, 0) console.log(sum) // - Manipulación // flat let nestedArray = [1, [2, [3, [4]]]] console.log(nestedArray) let flatArray = nestedArray.flat(1) console.log(flatArray) flatArray = nestedArray.flat(2) console.log(flatArray) flatArray = nestedArray.flat(3) console.log(flatArray) // flatMap let phrases = ["Hola mundo", "Adiós mundo"] let words = phrases.flatMap(phrase => phrase.split(" ")) console.log(words) // - Ordenación // sort let unsorted = ["b", "a", "d", "c"] let sorted = unsorted.sort() console.log(sorted) unsorted = [3, 4, 1, 6, 10] sorted = unsorted.sort((a, b) => a - b) console.log(sorted) // reverse sorted.reverse() console.log(sorted) // - Búsqueda // includes console.log(sorted.includes(4)) console.log(sorted.includes(5)) // find let firstEven = sorted.find(element => element % 2 === 0) console.log(firstEven) // findIndex let firstEvenIndex = sorted.findIndex(element => element % 2 === 0) console.log(firstEvenIndex) // Sets avanzados // - Operaciones // Eliminación de duplicados let numbersArray = [1, 2, 2, 3, 4, 5, 6, 6] numbersArray = [...new Set(numbersArray)] console.log(numbersArray) // Unión const setA = new Set([1, 2, 3]) const setB = new Set([2, 3, 4, 5]) const union = new Set([...setA, ...setB]) console.log(union) // Intersección const intersection = new Set([...setA].filter(element => setB.has(element))) console.log(intersection) // Diferencia const difference = new Set([...setA].filter(element => !setB.has(element))) console.log(difference) // - Conversión // Set a Array console.log([...setA]) // - Iteración // forEach setA.forEach(element => console.log(element)) // Maps avanzados // - Iteración let myMap = new Map([ ["name", "MoureDev"], ["age", 37] ]) myMap.forEach((value, key) => console.log(`${key}: ${value}`)) // - Conversión // Map a Array const arrayFromMap = Array.from(myMap) console.log(arrayFromMap) // Map a Objeto const objectFromMap = Object.fromEntries(myMap) console.log(objectFromMap) // Objeto a Map const mapFromObject = new Map(Object.entries(objectFromMap)) console.log(mapFromObject) ================================================ FILE: Intermediate/03-advanced-structures-exercises.js ================================================ /* Clase 23 - Estructuras avanzadas Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=7514 */ // 1. Utiliza map, filter y reduce para crear un ejemplo diferente al de la lección // 2. Dado un array de números, crea uno nuevo con dichos números elevados al cubo y filtra sólo los números pares // 3. Utiliza flat y flatMap para crear un ejemplo diferente al de la lección // 4. Ordena un array de números de mayor a menor // 5. Dados dos sets, encuentra la unión, intersección y diferencia de ellos // 6. Itera los resultados del ejercicio anterior // 7. Crea un mapa que almacene información se usuarios (nombre, edad y email) e itera los datos // 8. Dado el mapa anterior, crea un array con los nombres // 9. Dado el mapa anterior, obtén un array con los email de los usuarios mayores de edad y transfórmalo a un set // 10. Transforma el mapa en un objeto, a continuación, transforma el objeto en un mapa con clave el email de cada usuario y como valor todos los datos del usuario ================================================ FILE: Intermediate/04-advanced-objects.js ================================================ /* Clases 24 a 28 - Objetos y clases avanzados Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=7639 */ // Objetos avanzados // - Prototipos y Herencia // Prototipos let person = { name: "Brais", age: 37, greet() { console.log(`Hola, soy ${this.name}`) } } console.log(person.__proto__) console.log(Object.getPrototypeOf(person)) person.sayAge = function () { console.log(`Tengo ${this.age} años`) } console.log(person) person.sayAge() // Herencia let programmer = Object.create(person) programmer.language = "JavaScript" programmer.name = "MoureDev" console.log(person.name) console.log(person.language) console.log(programmer.name) console.log(programmer.age) console.log(programmer.language) programmer.greet() programmer.sayAge() // - Métodos estáticos y de instancia function Person(name, age) { this.name = name this.age = age } Person.prototype.greet = function () { console.log(`Hola, soy ${this.name}`) } let newPerson = new Person("Brais", 37) newPerson.greet() // - Métodos avanzados // assign let personCore = { name: "Brais" } let personDetails = { age: 37, alias: "MoureDev" } let fullPerson = Object.assign(personCore, personDetails) console.log(fullPerson) // keys, values, entries console.log(Object.keys(fullPerson)) console.log(Object.values(fullPerson)) console.log(Object.entries(fullPerson)) ================================================ FILE: Intermediate/05-advanced-classes.js ================================================ /* Clases 29 a 37 - Objetos y clases avanzados Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=9096 */ // Clases avanzadas class Person { constructor(name, age) { this.name = name this.age = age } greet() { console.log(`Hola, soy ${this.name}`) } } const person = new Person("Brais", 37) person.greet() person.sayAge = function () { console.log(`Tengo ${this.age} años`) } person.sayAge() // - Abstracción class Animal { constructor(name) { if (new.target === Animal) { throw new Error("No se puede instanciar una clase abstracta") } this.name = name } makeSound() { throw new Error("Este método tiene que ser implementado por la subclase") } } // Error // const animal = new Animal("Mou") // console.log(animal) // - Polimorfismo class Cat extends Animal { makeSound() { console.log("Miau!") } } class Dog extends Animal { makeSound() { console.log("Guau!") } } const cat = new Cat("MoureCat") console.log(cat) cat.makeSound() const dog = new Dog("MoureDog") console.log(dog) dog.makeSound() // - Mixins const FlyMixin = { fly() { console.log(`${this.name} está volando`) } } class Bird extends Animal { } class Dragon extends Animal { } Object.assign(Bird.prototype, FlyMixin) Object.assign(Dragon.prototype, FlyMixin) const bird = new Bird("MoureBird") console.log(bird.name) bird.fly() const dragon = new Dragon("MoureDragon") console.log(dragon.name) dragon.fly() // - Patrón Singleton class Session { constructor(name) { if (Session.instance) { return Session.instance } this.name = name Session.instance = this } } const session1 = new Session("Brais Moure") const session2 = new Session() console.log(session1.name) console.log(session2.name) console.log(session1 === session2) const session3 = new Session("MoureDev") console.log(session3.name) console.log(session2 === session3) // - Symbol const ID = Symbol("id") class User { constructor(name) { this.name = name this[ID] = Math.random() } getId() { return this[ID] } } const user = new User("Brais") console.log(user.name) console.log(user.ID) console.log(user.getId()) // - instanceof class Car { } const car = new Car() console.log(car instanceof Car) // - create const anotherCar = Object.create(Car.prototype) console.log(anotherCar instanceof Car) // - Proxy const proxy = { get(target, property) { console.log(`Se accede a la propiedad ${property}`) return target[property] }, set(target, property, value) { if (property === "balance" && value < 0) { throw new Error("El saldo no puede ser negativo") } target[property] = value } } class BankAccount { constructor(balance) { this.balance = balance } } const account = new Proxy(new BankAccount(100), proxy) console.log(account.balance) account.balance = 50 console.log(account.balance) // Error // account.balance = -10 ================================================ FILE: Intermediate/06-advanced-objects-classes-exercises.js ================================================ /* Clase 38 - Objetos y clases avanzados Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=11832 */ // 1. Agregega una función al prototipo de un objeto // 2. Crea un objeto que herede de otro // 3. Define un método de instancia en un objeto // 4. Haz uso de get y set en un objeto // 5. Utiliza la operación assign en un objeto // 6. Crea una clase abstracta // 7. Utiliza polimorfismo en dos clases diferentes // 8. Implementa un Mixin // 9. Crea un Singleton // 10. Desarrolla un Proxy ================================================ FILE: Intermediate/07-async.js ================================================ /* Clases 39 a 44 - Asincronía Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=11890 */ // Programación asíncrona // Código síncrono console.log("Inicio") for (let i = 0; i < 100000000; i++) { } console.log("Fin") // Event Loop (Bucle de eventos) // Componentes del Event Loop: // 1. Call Stack (Pila de ejecución) // 2. Web APIs (APIs del navegador) o Node.js: // 3. Task Queue (setTimeout()) y Microtask Queue (Promesas) // Flujo del Event Loop: // 1. Call Stack // 2. Operaciones asíncronas -> Web APIs o Node.js // 3. Operación termina -> La coloca en Task Queue o Microtask Queue // 4. Si Call Stack vacío -> Mueve tareas del Microtask Queue o Task Queue al Call Stack // 5. El proceso se repite // Código asíncrono // - Callbacks console.log("Inicio") setTimeout(() => { console.log("Esto se ejecuta después de 2 segundos") }, 2000) console.log("Fin") // - Problema: Callback Hell function step1(callback) { setTimeout(() => { console.log("Paso 1 completado") callback() }, 1000) } function step2(callback) { setTimeout(() => { console.log("Paso 2 completado") callback() }, 1000) } function step3(callback) { setTimeout(() => { console.log("Paso 3 completado") callback() }, 1000) } step1(() => { step2(() => { step3(() => { console.log("Todos los pasos completados") }) }) }) // - Promesas const promise = new Promise((resolve, reject) => { // IMPORTANTE: Inicialmente escribí setInterval, pero lo correcto es setTimeout // setInterval se ejecutaría indefinidamente cada 4s, y el proceso nunca finalizaría setTimeout(() => { const ok = false if (ok) { resolve("Operación exitosa") } else { reject("Se ha producido un error") } }, 4000) }) promise .then(result => { console.log(result) }) .catch(error => { console.log(error) }) // - Encadenamiento de promesas function step1Promise() { return new Promise(resolve => { setTimeout(() => { console.log("Paso 1 con promesa completado") resolve() }, 1000) }) } function step2Promise() { return new Promise(resolve => { setTimeout(() => { console.log("Paso 2 con promesa completado") resolve() }, 1000) }) } function step3Promise() { return new Promise(resolve => { setTimeout(() => { console.log("Paso 3 con promesa completado") resolve() }, 1000) }) } step1Promise() .then(step2Promise) .then(step3Promise) .then(() => { console.log("Todos los pasos con promesa completados") }) // - Async/Await function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } async function process() { console.log("Inicio del proceso") await wait(5000) console.log("Proceso después de 5 segundos") await wait(1000) console.log("Proceso después de 1 segundo") await wait(2000) console.log("Proceso después de 2 segundos") console.log("Fin del proceso") } process() ================================================ FILE: Intermediate/08-async-exercises.js ================================================ /* Clase 45 - Asincronía Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=14558 */ // 1. Crea una función para saludar que reciba un nombre y un callback. // El callback debe ejecutarse después de 2 segundos y mostrar en consola "Hola, [nombre]". // 2. Crea tres funciones task1(callback), task2(callback) y task3(callback). // Cada función debe tardar 1 segundo en ejecutarse y luego llamar al callback. // 3. Crea una función para verificar un número que retorne una Promesa. // Si el número es par, la promesa se resuelve con el mensaje "Número par". // Si el número es impar, la promesa se rechaza con el mensaje "Número impar". // 4. Crea tres funciones que devuelvan promesas: // firstTask(): tarda 1s y muestra "Primera tarea completada". // secondTask(): tarda 2s y muestra "Segunda tarea completada". // thirdTask(): tarda 1.5s y muestra "Tercera tarea completada". // 5. Transforma el ejercicio anterior de Promesas en una función async/await llamada executeTasks(). // 6. Crea una función getUser(id) que devuelva una promesa y simule una llamada a una API (que se demore 2s). // Si el id es menor a 5, la promesa se resuelve con { id, nombre: "Usuario " + id }. // Si el id es 5 o mayor, la promesa se rechaza con el mensaje "Usuario no encontrado". // Usa async/await para llamar a getUser(id) y maneja los errores con try/catch. // 7. Intenta predecir el resultado de este código antes de ejecutarlo en la consola: // console.log("Inicio") // setTimeout(() => console.log("setTimeout ejecutado"), 0) // Promise.resolve().then(() => console.log("Promesa resuelta")) // console.log("Fin") // 8. Crea tres funciones que devuelvan promesas con tiempos de espera distintos. // A continuación, usa Promise.all() para ejecutarlas todas al mismo tiempo y mostrar "Todas las promesas resueltas" cuando terminen. // 9. Crea una función waitSeconds(segundos) que use setTimeout dentro de una Promesa para esperar la cantidad de segundos indicada. // A continuación, usa async/await para que se espere 3 segundos antes de mostrar "Tiempo finalizado" en consola. // 10. Crea una simulación de un cajero automático usando asincronía. // - La función checkBalance() tarda 1s y devuelve un saldo de 500$. // - La función withdrawMoney(amount) tarda 2s y retira dinero si hay suficiente saldo, o devuelve un error si no hay fondos. // - Usa async/await para hacer que el usuario intente retirar 300$ y luego 300$ más. // // Posible salida esperada: // Saldo disponible: 500$ // Retirando 300$... // Operación exitosa, saldo restante: 200$ // Retirando 300$... // Error: Fondos insuficientes ================================================ FILE: Intermediate/09-apis.js ================================================ /* Clases 46 a 59 - APIs Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=14777 */ // Manejo de APIs // - APIs REST (HTTP + URLs + JSON) // Métodos HTTP: // - GET // - POST // - PUT // - DELETE // Códigos de respuesta HTTP: // - 200 OK // - 201 // - 400 // - 404 // - 500 // Consumir una API // https://jsonplaceholder.typicode.com // GET fetch("https://jsonplaceholder.typicode.com/posts") .then(response => { // Transforma la respuesta a JSON return response.json() }) .then(data => { // Procesa los datos console.log(data) }) .catch(error => { // Captura errores console.log("Error", error) }) // Uso de Async/Await async function getPosts() { try { const response = await fetch("https://jsonplaceholder.typicode.com/posts") const data = await response.json() console.log(data) } catch (error) { console.log("Error", error) } } getPosts() // Solicitud POST async function createPost() { try { const newPost = { userId: 1, title: "Este es el título de mi post", body: "Este es el cuerpo de mi post" } const response = await fetch("https://jsonplaceholder.typicode.com/posts", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newPost) }) const data = await response.json() console.log(data) } catch (error) { console.log("Error", error) } } createPost() // Herramientas para realizar peticiones HTTP // - https://postman.com // - https://apidog.com // - https://thunderclient.com // Manejo de errores fetch("https://jsonplaceholder.typicode.com/mouredev") .then(response => { if (!response.ok) { throw Error(`Status HTTP: ${response.status}`) } return response.json() }) .catch(error => { console.log("Error", error) }) // Métodos HTTP adicionales // - PATCH // - OPTIONS async function partialPostUpdate() { try { const response = await fetch("https://jsonplaceholder.typicode.com/posts/10", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title: "Este es el nuevo título de mi post" }) }) const data = await response.json() console.log(data) } catch (error) { console.log("Error", error) } } partialPostUpdate() // Autenticación mediante API Key async function getWeather(city) { // https://openweathermap.org const apiKey = "TU_API_KEY" const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}` try { const response = await fetch(url) const data = await response.json() console.log(data) } catch (error) { console.log("Error", error) } } getWeather("Madrid") // Otros métodos de Autenticación y Autorización // - Bearer Tokens // - JWT // Versionado de APIs // - https://api.example.com/v1/resources // - https://api.example.com/v2/resources // Otras APIs async function getPokemon(pokemon) { // https://pokeapi.co const url = `https://pokeapi.co/api/v2/pokemon/${pokemon}` try { const response = await fetch(url) const data = await response.json() console.log(`Habilidades de ${data.name}`) data.abilities.forEach(ability => { console.log(ability.ability.name) }) } catch (error) { console.log("Error", error) } } getPokemon("pikachu") ================================================ FILE: Intermediate/10-apis-exercises.js ================================================ /* Clase 60 - APIs Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=18710 */ // 1. Realiza una petición GET con fetch() a JSONPlaceholder y muestra en la consola la lista de publicaciones // 2. Modifica el ejercicio anterior para que verifique si la respuesta es correcta usando response.ok. Si no lo es, lanza y muestra un error // 3. Reescribe el ejercicio 1 usando la sintaxis async/await en lugar de promesas // 4. Realiza una petición POST a JSONPlaceholder para crear una nueva publicación. Envía un objeto con propiedades como title o body // 5. Utiliza el método PUT para actualizar completamente un recurso (por ejemplo, modificar una publicación) en JSONPlaceholder // 6. Realiza una petición PATCH para modificar únicamente uno o dos campos de un recurso existente // 7. Envía una solicitud DELETE a la API para borrar un recurso (por ejemplo, una publicación) y verifica la respuesta // 8. Crea una función que realice una solicitud GET (la que quieras) a OpenWeatherMap // 9. Utiliza la PokéAPI para obtener los datos de un Pokémon concreto, a continuación los detalles de la especie y, finalmente, la cadena evolutiva a partir de la especie // 10. Utiliza una herramienta como Postman o Thunder Client para probar diferentes endpoint de una API ================================================ FILE: Intermediate/11-dom.js ================================================ /* Clases 61 a 68 - DOM Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=18822 */ // Manejo del DOM (Document Object Model) console.log(document) // - Selección de elementos // Métodos básicos (selector HTML) const myElementById = document.getElementById("id") const myElementsByClass = document.getElementsByClassName("class") const myElementsByTag = document.getElementsByTagName("tag") // Métodos más modernos (selector CSS) document.querySelector(".paragraph") document.querySelectorAll(".paragraph") // - Manipulación de elementos const title = document.getElementById("title") title.textContent = "Hola JavaScript" const container = document.querySelector(".container") container.innerHTML = "

Esto es un nuevo párrafo

" // - Modificación de atributos // Obtención del atributo const link = document.querySelector("a") const url = link.getAttribute("href") // Establecimiento del atributo link.setAttribute("href", "https://example.com") // Comprobación de atributo const hasTarget = link.hasAttribute("target") // Eliminación de atributos link.removeAttribute("target") // - Interacción con clases CSS const box = document.querySelector(".box") box.classList.add("selected") box.classList.remove("selected") box.classList.toggle("selected") const button = document.querySelector("button") button.style.backgroundColor = "blue" button.style.color = "white" button.style.padding = "10px" // - Creación y eliminación de elementos // Creación const newParagraph = document.createElement("p") newParagraph.textContent = "Este es un nuevo párrafo creado desde JS" newParagraph.style.padding = "8px" container.appendChild(newParagraph) const itemsList = document.querySelector("ul") const newItem = document.createElement("li") newItem.textContent = "Nuevo elemento" // Inserción en un lugar concreto const secondItem = itemsList.children[1] itemsList.insertBefore(newItem, secondItem) itemsList.append(newItem) itemsList.prepend(newItem) secondItem.before(newItem) secondItem.after(newItem) // Eliminación newParagraph.remove() // Eliminación tradicional const parent = newParagraph.parentElement parent.removeChild(newParagraph) // - Elementos del DOM function showMsg() { alert("Clic!") } const sendButton = document.querySelector("#send") sendButton.addEventListener("click", showMsg) sendButton.addEventListener("click", () => { alert("Clic con una arrow function!") }) // Eventos comunes document.addEventListener("DOMContentLoader", () => { console.log("El DOM está completamente cargado") }) sendButton.addEventListener("mouseenter", () => { sendButton.style.backgroundColor = "green" }) sendButton.addEventListener("mouseleave", () => { sendButton.style.backgroundColor = "blue" }) const form = document.querySelector("form") form.addEventListener("submit", (event) => { // Código }) ================================================ FILE: Intermediate/12-dom-example.html ================================================ HTML de ejemplo

Mi título

================================================ FILE: Intermediate/13-dom-example.js ================================================ /* Clase 69 - DOM Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=21754 */ console.log(document) const myH1 = document.querySelector("h1") console.log(myH1) myH1.textContent = "Mi nuevo título" ================================================ FILE: Intermediate/14-tasklist.html ================================================ Lista de tareas

Mis tareas

================================================ FILE: Intermediate/15-tasklist.js ================================================ /* Clase 70 - DOM Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=22342 */ const text = document.getElementById("text") const button = document.getElementById("button") const list = document.getElementById("list") function addTask() { if (text.value === "") return const newElement = document.createElement("li") newElement.textContent = text.value newElement.addEventListener("click", () => { newElement.remove() }) list.appendChild(newElement) text.value = "" } button.addEventListener("click", addTask) text.addEventListener("keypress", (event) => { if (event.key === "Enter") { addTask() } }) ================================================ FILE: Intermediate/16-dom-exercises.js ================================================ /* Clase 71 - DOM Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=23010 */ // 1. Crea un elemento (por ejemplo, un

) y cambia su contenido a "¡Hola Mundo!"" al cargar la página // 2. Inserta una imagen con id="myImage" y cambia su atributo src a otra URL // 3. Crea un
sin clases y agrega la clase resaltado cuando se cargue la página // 4. Crea un párrafo con id="paragraph" y cambia su color de texto a azul // 5. Agrega un botón que, al hacer clic, cree un nuevo elemento
  • con el texto "Nuevo elemento y lo agregue a una lista
      // 6. Crea un párrafo con id="deleteParagraph" y un botón. Al hacer clic en el botón, elimina el párrafo del DOM // 7. Crea un
      con algún texto y reemplaza su contenido por un

      con el mensaje "Nuevo Contenido" // 8. Crea un botón con id="greetBtn" y añade un evento que muestre una alerta con el mensaje "¡Hola!" al hacer clic // 9. Crea un y un
      . Al escribir en el input, el
      se debe actualizarse mostrando lo que se escribe // 10. Crea un botón con id="backgroundBtn" y, al hacer clic, cambia el color de fondo del a un color diferente ================================================ FILE: Intermediate/17-debugging.js ================================================ /* Clases 72 a 73 - Depuración Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=23085 */ // Depuración // console.log() (básico) function sum(a, b) { console.log("a:", a) console.log("typeof a:", typeof a) console.log("b:", b) console.log("typeof b:", typeof b) return a + b } console.log(sum(3, "5")) // Depurador (profesional) function divide(a, b) { if (b === 0) { throw new Error("No se puede dividir por cero") } return a / b } // console.log(divide(5, 0)) Error ================================================ FILE: Intermediate/18-debugging-exercises.js ================================================ /* Clases 74 - Depuración Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=24329 */ // 1. Crea un código con un error lógico y usa VS Code para encontrarlo // 2. Experimenta con breakpoints y observa cómo cambia el flujo de ejecución ================================================ FILE: Intermediate/19-regex.js ================================================ /* Clases 75 a 78 - Regex Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=24363 */ // Expresiones regulares // - Sintaxis const regex = /abc/ const regex2 = RegExp("abc") const text = "Hola abc JavaScript" // test: verifica coincidencia con true o false console.log(regex.test(text)) console.log(regex2.test(text)) const text2 = "Mi edad es 37" const regex3 = /\d/g const regex4 = /[4-6]/ console.log(regex3.test(text2)) console.log(regex4.test(text2)) // replace: reemplaza el texto que coincide con el patrón const regex5 = /JavaScript/ console.log("Hola JavaScript".replace(regex5, "JS")) const text3 = "Estoy contando 1 2 3 4 5 6 7" console.log(text3.replace(regex3, "[número]")) // exec: retorna detalles de la coincidencia console.log(regex3.exec(text3)) while ((match = regex3.exec(text3)) !== null) { console.log(match) } ================================================ FILE: Intermediate/20-regex-exercises.js ================================================ /* Clase 79 - Regex Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=25888 */ // 1. Crea una RegEx que valide correos electrónicos // 2. Crea una RegEx obtenga Hashtags de un Texto // 3. Crea una RegEx que valide contraseñas seguras (mínimo 8 caracteres, al menos una letra y un número) // NOTA: Aplícalas utilizando diferentes operaciones ================================================ FILE: Intermediate/21-testing.js ================================================ /* Clases 80 a 81 - Testing Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=25938 */ // Testing // - Tipos de testing // Pruebas unitarias function sum(a, b) { return a + b } module.exports = sum console.log(sum(3, 5) === 8) // Pruebas de integración // Pruebas end-to-end (E2E) ================================================ FILE: Intermediate/22-testing.test.js ================================================ /* Clases 80 a 81 - Testing Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=25938 */ const sum = require('./21-testing') test("Suma de 3 + 5 tiene que ser 8", () => { expect(sum(3, 5)).toBe(8) }) test("Suma de 3 + 3 tiene que ser 6", () => { expect(sum(3, 4)).toBe(6) }) ================================================ FILE: Intermediate/23-testing-exercises.js ================================================ /* Clase 82 - Testing Vídeo: https://youtu.be/iJvLAZ8MJ2E?t=26946 */ // 1. Crea una función isEven(number) que devuelva true si el número es par y false si es impar // 2. Escribe una prueba en Jest para verificar que la función funciona correctamente // 3. Verifica que la prueba se ejecuta satisfactoriamente ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # Hello JavaScript [![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-yellow?style=for-the-badge&logo=javascript&logoColor=white&labelColor=101010)](https://developer.mozilla.org/es/docs/Web/JavaScript) [![NodeJS](https://img.shields.io/badge/NODEJS-v20+-green?style=for-the-badge&logo=nodedotjs&logoColor=white&labelColor=101010)](https://nodejs.org/) ## Curso para aprender el lenguaje de programación JavaScript desde cero y para principiantes ![](./Images/header.jpg) ### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev) > ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias! ## Clases en vídeo ### Curso de fundamentos desde cero * [Introducción](https://youtu.be/1glVfFxj8a4) * [1 - Contexto](https://youtu.be/1glVfFxj8a4?t=174) * [2 - Historia](https://youtu.be/1glVfFxj8a4?t=322) * [3 - JavaScript y Java](https://youtu.be/1glVfFxj8a4?t=665) * [4 - Utilización](https://youtu.be/1glVfFxj8a4?t=931) * [5 - Especificación ECMAScript](https://youtu.be/1glVfFxj8a4?t=1017) * [6 - Motor V8](https://youtu.be/1glVfFxj8a4?t=1293) * [7 - Referencia](https://youtu.be/1glVfFxj8a4?t=1403) * [8 - Ejercicios prácticos](https://youtu.be/1glVfFxj8a4?t=1621) * [9 - Versión](https://youtu.be/1glVfFxj8a4?t=1705) * [10 - Explorador web](https://youtu.be/1glVfFxj8a4?t=1768) * [11 - Playground](https://youtu.be/1glVfFxj8a4?t=1893) * [12 - Instalación](https://youtu.be/1glVfFxj8a4?t=1988) * [13 - Editor de código](https://youtu.be/1glVfFxj8a4?t=2256) * [14 - Buenas prácticas](https://youtu.be/1glVfFxj8a4?t=2311) * [15 - Hola mundo](https://youtu.be/1glVfFxj8a4?t=2390) | [Código](./Basic/00-helloworld.js) * [16 - Variables](https://youtu.be/1glVfFxj8a4?t=3049) | [Código](./Basic/01-variables.js) * [17 - Tipos de datos](https://youtu.be/1glVfFxj8a4?t=3599) | [Código](./Basic/02-datatypes.js) * [18 - Ejercicios: primeros pasos](https://youtu.be/1glVfFxj8a4?t=4733) | [Ejercicios](./Basic/03-beginner-exercises.js) * [19 - Operadores](https://youtu.be/1glVfFxj8a4?t=4937) | [Código](./Basic/04-operators.js) * [20 - Ejercicios: Operadores](https://youtu.be/1glVfFxj8a4?t=6458) | [Ejercicios](./Basic/05-operators-exercises.js) * [21 - Strings](https://youtu.be/1glVfFxj8a4?t=6565) | [Código](./Basic/06-strings.js) * [22 - Ejercicios: Strings](https://youtu.be/1glVfFxj8a4?t=7226) | [Ejercicios](./Basic/07-strings-exercises.js) * [23 - Condicionales](https://youtu.be/1glVfFxj8a4?t=7277) | [Código](./Basic/08-conditionals.js) * [24 - Ejercicios: Condicionales](https://youtu.be/1glVfFxj8a4?t=8652) | [Ejercicios](./Basic/09-conditionals-exercises.js) * [25 - Arrays](https://youtu.be/1glVfFxj8a4?t=8741) | [Código](./Basic/10-array.js) * [26 - Sets](https://youtu.be/1glVfFxj8a4?t=9952) | [Código](./Basic/11-set.js) * [27 - Maps](https://youtu.be/1glVfFxj8a4?t=10755) | [Código](./Basic/12-map.js) * [28 - Ejercicios: Estructuras](https://youtu.be/1glVfFxj8a4?t=11451) | [Ejercicios](./Basic/13-structures-exercises.js) * [29 - Bucles](https://youtu.be/1glVfFxj8a4?t=11575) | [Código](./Basic/14-loops.js) * [30 - Ejercicios: Bucles](https://youtu.be/1glVfFxj8a4?t=12732) | [Ejercicios](./Basic/15-loops-exercises.js) * [31 - Funciones](https://youtu.be/1glVfFxj8a4?t=12829) | [Código](./Basic/16-functions.js) * [32 - Ejercicios: Funciones](https://youtu.be/1glVfFxj8a4?t=14146) | [Ejercicios](./Basic/17-functions-exercises.js) * [33 - Objetos](https://youtu.be/1glVfFxj8a4?t=14229) | [Código](./Basic/18-objects.js) * [34 - Ejercicios: Objetos](https://youtu.be/1glVfFxj8a4?t=15675) | [Ejercicios](./Basic/19-objects-exercises.js) * [35 - Desestructuración y propagación](https://youtu.be/1glVfFxj8a4?t=15747) | [Código](./Basic/20-destructuring-spreading.js) * [36 - Ejercicios: Desestructuración y propagación](https://youtu.be/1glVfFxj8a4?t=16802) | [Ejercicios](./Basic/21-destructuring-spreading-exercises.js) * [37 - Clases](https://youtu.be/1glVfFxj8a4?t=16864) | [Código](./Basic/22-classes.js) * [38 - Herencia de clases](https://youtu.be/1glVfFxj8a4?t=17999) | [Código](./Basic/22-classes.js) * [39 - Ejercicios: Clases](https://youtu.be/1glVfFxj8a4?t=18630) | [Ejercicios](./Basic/23-classes-exercises.js) * [40 - Manejo de errores](https://youtu.be/1glVfFxj8a4?t=18751) | [Código](./Basic/24-error-handling.js) * [41 - Ejercicios: Manejo de errores](https://youtu.be/1glVfFxj8a4?t=20392) | [Ejercicios](./Basic/25-error-handling-exercises.js) * [42 - Console](https://youtu.be/1glVfFxj8a4?t=20444) | [Código](./Basic/26-console-methods.js) * [43 - Ejercicios: Console](https://youtu.be/1glVfFxj8a4?t=21421) | [Ejercicios](./Basic/27-console-methods-exercises.js) * [44 - Módulos](https://youtu.be/1glVfFxj8a4?t=21480) | [Código exportación](./Basic/28-export-modules.js) | [Código importación](./Basic/29-import-modules.js) | [Código externos](./Basic/30-import-external-modules.cjs) * [45 - Ejercicios: Módulos](https://youtu.be/1glVfFxj8a4?t=22720) | [Ejercicios](./Basic/31-modules-exercises.js) | [package.json](./Basic/package.json) * [Despedida](https://youtu.be/1glVfFxj8a4?t=22776) ### Curso de fundamentos intermedio (continuación del desde cero) * [Introducción](https://youtu.be/iJvLAZ8MJ2E) * [1 - Primeros pasos](https://youtu.be/iJvLAZ8MJ2E?t=279) Funciones avanzadas | [Código](./Intermediate/00-advanced-functions.js) * [2 - Ciudadanos de primera clase](https://youtu.be/iJvLAZ8MJ2E?t=346) * [3 - Arrow functions](https://youtu.be/iJvLAZ8MJ2E?t=782) * [4 - IIFE](https://youtu.be/iJvLAZ8MJ2E?t=1278) * [5 - Parámetros rest](https://youtu.be/iJvLAZ8MJ2E?t=1873) * [6 - Operador Spread](https://youtu.be/iJvLAZ8MJ2E?t=2126) * [7 - Closures](https://youtu.be/iJvLAZ8MJ2E?t=2356) * [8 - Recursividad](https://youtu.be/iJvLAZ8MJ2E?t=2650) * [9 - Funciones parciales](https://youtu.be/iJvLAZ8MJ2E?t=3013) * [10 - Currying](https://youtu.be/iJvLAZ8MJ2E?t=3473) * [11 - Callbacks](https://youtu.be/iJvLAZ8MJ2E?t=3675) * [12 - Ejercicios: Funciones avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=4112) | [Ejercicios](./Intermediate/01-advanced-functions-exercises.js) Estructuras avanzadas | [Código](./Intermediate/02-advanced-structures.js) * [13 - Estructuras avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=4355) * [14 - Arrays avanzados: métodos funcionales](https://youtu.be/iJvLAZ8MJ2E?t=4411) * [15 - Arrays avanzados: manipulación](https://youtu.be/iJvLAZ8MJ2E?t=5244) * [16 - Arrays avanzados: ordenación](https://youtu.be/iJvLAZ8MJ2E?t=5621) * [17 - Arrays avanzados: búsqueda](https://youtu.be/iJvLAZ8MJ2E?t=5979) * [18 - Sets avanzados: operaciones](https://youtu.be/iJvLAZ8MJ2E?t=6288) * [19 - Sets avanzados: conversión](https://youtu.be/iJvLAZ8MJ2E?t=6949) * [20 - Sets avanzados: iteración](https://youtu.be/iJvLAZ8MJ2E?t=6992) * [21 - Maps avanzados: iteración](https://youtu.be/iJvLAZ8MJ2E?t=7061) * [22 - Maps avanzados: conversión](https://youtu.be/iJvLAZ8MJ2E?t=7207) * [23 - Ejercicios: Estructuras avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=7514) | [Ejercicios](./Intermediate/03-advanced-structures-exercises.js) Objetos y clases avanzados | [Código Objetos](./Intermediate/04-advanced-objects.js) | [Código Clases](./Intermediate/05-advanced-classes.js) * [24 - Objetos avanzados](https://youtu.be/iJvLAZ8MJ2E?t=7639) * [25 - Prototipos](https://youtu.be/iJvLAZ8MJ2E?t=7695) * [26 - Herencia](https://youtu.be/iJvLAZ8MJ2E?t=8068) * [27 - Métodos estáticos y de instancia](https://youtu.be/iJvLAZ8MJ2E?t=8577) * [28 - Métodos avanzados](https://youtu.be/iJvLAZ8MJ2E?t=8896) * [29 - Clases avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=9096) * [30 - Abstracción](https://youtu.be/iJvLAZ8MJ2E?t=9408) * [31 - Polimorfismo](https://youtu.be/iJvLAZ8MJ2E?t=9694) * [32 - Mixins](https://youtu.be/iJvLAZ8MJ2E?t=9956) * [33 - Singleton](https://youtu.be/iJvLAZ8MJ2E?t=10454) * [34 - Symbol](https://youtu.be/iJvLAZ8MJ2E?t=10901) * [35 - instanceof](https://youtu.be/iJvLAZ8MJ2E?t=11264) * [36 - create](https://youtu.be/iJvLAZ8MJ2E?t=11331) * [37 - Proxy](https://youtu.be/iJvLAZ8MJ2E?t=11375) * [38 - Ejercicios: Objetos y clases avanzados](https://youtu.be/iJvLAZ8MJ2E?t=11832) | [Ejercicios](./Intermediate/06-advanced-objects-classes-exercises) Asincronía | [Código](./Intermediate/07-async.js) * [39 - Asincronía](https://youtu.be/iJvLAZ8MJ2E?t=11890) * [40 - Código síncrono](https://youtu.be/iJvLAZ8MJ2E?t=12245) * [41 - Event Loop](https://youtu.be/iJvLAZ8MJ2E?t=12366) * [42 - Callbacks](https://youtu.be/iJvLAZ8MJ2E?t=12729) * [43 - Promesas](https://youtu.be/iJvLAZ8MJ2E?t=13349) * [44 - Async/Await](https://youtu.be/iJvLAZ8MJ2E?t=14171) * [45 - Ejercicios: Asincronía](https://youtu.be/iJvLAZ8MJ2E?t=14558) | [Ejercicios](./Intermediate/08-async-exercises.js) APIs | [Código](./Intermediate/09-apis.js) * [46 - APIs](https://youtu.be/iJvLAZ8MJ2E?t=14777) * [47 - API REST](https://youtu.be/iJvLAZ8MJ2E?t=14973) * [48 - Métodos HTTP](https://youtu.be/iJvLAZ8MJ2E?t=15134) * [49 - Códigos de respuesta HTTP](https://youtu.be/iJvLAZ8MJ2E?t=15294) * [50 - GET](https://youtu.be/iJvLAZ8MJ2E?t=15477) * [51 - Async/Await en APIs](https://youtu.be/iJvLAZ8MJ2E?t=16400) * [52 - POST](https://youtu.be/iJvLAZ8MJ2E?t=16626) * [53 - Herramientas para realizar peticiones HTTP](https://youtu.be/iJvLAZ8MJ2E?t=17088) * [54 - Manejo de errores](https://youtu.be/iJvLAZ8MJ2E?t=17325) * [55 - Métodos HTTP adicionales](https://youtu.be/iJvLAZ8MJ2E?t=17619) * [56 - Autenticación mediante API Key](https://youtu.be/iJvLAZ8MJ2E?t=17770) * [57 - Otros métodos de autenticación y autorización](https://youtu.be/iJvLAZ8MJ2E?t=18244) * [58 - Versionado de APIs](https://youtu.be/iJvLAZ8MJ2E?t=18323) * [59 - Otras APIs](https://youtu.be/iJvLAZ8MJ2E?t=18441) * [60 - Ejercicios: APIs](https://youtu.be/iJvLAZ8MJ2E?t=18710) | [Ejercicios](./Intermediate/10-apis-exercises.js) DOM | [Código](./Intermediate/11-dom.js) * [61 - DOM](https://youtu.be/iJvLAZ8MJ2E?t=18822) * [62 - Estructura del DOM](https://youtu.be/iJvLAZ8MJ2E?t=19105) * [63 - Métodos de selección](https://youtu.be/iJvLAZ8MJ2E?t=19172) * [64 - Manipulación de elementos](https://youtu.be/iJvLAZ8MJ2E?t=19792) * [65 - Modificación de atributos](https://youtu.be/iJvLAZ8MJ2E?t=19996) * [66 - Interacción con clases CSS](https://youtu.be/iJvLAZ8MJ2E?t=20326) * [67 - Creación y eliminación de elementos](https://youtu.be/iJvLAZ8MJ2E?t=20787) * [68 - Elementos y eventos del DOM](https://youtu.be/iJvLAZ8MJ2E?t=21377) * [69 - Ejemplos: acceso al DOM](https://youtu.be/iJvLAZ8MJ2E?t=21754) | Ejemplo simple: [HTML](./Intermediate/12-dom-example.html) - [JS](./Intermediate/13-dom-example.js) * [70 - Ejemplos: lista de tareas](https://youtu.be/iJvLAZ8MJ2E?t=22342) Ejemplo lista de tareas: [HTML](./Intermediate/14-tasklist.html) - [JS](./Intermediate/15-tasklist.js) * [71 - Ejercicios: DOM](https://youtu.be/iJvLAZ8MJ2E?t=23010) | [Ejercicios](./Intermediate/16-dom-exercises.js) Depuración | [Código](./Intermediate/17-debugging.js) * [72 - Depuración](https://youtu.be/iJvLAZ8MJ2E?t=23085) * [73 - Depurador](https://youtu.be/iJvLAZ8MJ2E?t=23370) * [74 - Ejercicios: Depuración](https://youtu.be/iJvLAZ8MJ2E?t=24329) | [Ejercicios](./Intermediate/18-debugging-exercises.js) Regex | [Código](./Intermediate/19-regex.js) * [75 - Regex](https://youtu.be/iJvLAZ8MJ2E?t=24363) * [76 - Sintaxis: test](https://youtu.be/iJvLAZ8MJ2E?t=24444) * [77 - Sintaxis: replace](https://youtu.be/iJvLAZ8MJ2E?t=24989) * [78 - Sintaxis: exec](https://youtu.be/iJvLAZ8MJ2E?t=25365) * [79 - Ejercicios: Regex](https://youtu.be/iJvLAZ8MJ2E?t=25888) | [Ejercicios](./Intermediate/20-regex-exercises.js) Testing | [Código](./Intermediate/21-testing.js) | [Test](./Intermediate/22-testing.test.js) * [80 - Testing](https://youtu.be/iJvLAZ8MJ2E?t=25938) * [81 - Jest](https://youtu.be/iJvLAZ8MJ2E?t=26272) * [82 - Ejercicios: Testing](https://youtu.be/iJvLAZ8MJ2E?t=26946) | [Ejercicios](./Intermediate/23-testing-exercises.js) * [Despedida](https://youtu.be/iJvLAZ8MJ2E?t=26970) ## Enlaces de interés * Impacto: [Stack Overflow](https://survey.stackoverflow.co/2023/#most-popular-technologies-language) | [GitHub](https://github.blog/2023-11-08-the-state-of-open-source-and-ai/) | [Índice TIOBE](https://www.tiobe.com/tiobe-index/) | [Google Trends](https://trends.google.es/trends/explore?cat=5&date=today%205-y&q=%2Fm%2F02p97,%2Fm%2F05z1_,%2Fm%2F07sbkfb&hl=es) * [Historia](https://es.wikipedia.org/wiki/JavaScript) * [Especificación ECMAScript](https://tc39.es/ecma262/) * [Documentación Mozilla](https://developer.mozilla.org/es/docs/Web/JavaScript) * [Documentación W3Schools](https://www.w3schools.com/js/) * [Documentación JS Info](https://es.javascript.info/) * [Libro Eloquent JavaScript](https://eloquentjavascript.net/) * [Playground](https://runjs.app/play) * [Node.js](https://nodejs.org) * Exploradores: [Chrome](https://www.google.com/intl/es_es/chrome/) | [Brave](https://brave.com/download/) * [Visual Studio Code](https://code.visualstudio.com/) * [Guía de estilo](https://google.github.io/styleguide/jsguide.html) * Clientes HTTP: [Postman](https://postman.com) | [Apidog](https://apidog.com) | [Thunder Client](https://thunderclient.com) * APIs: [JSONPlaceholder](https://jsonplaceholder.typicode.com) | [OpenWeather](https://openweathermap.org) | [PokéAPI](https://pokeapi.co) * Expresiones regulares: [Documentación](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet ) | [Regex101](https://regex101.com/) * [Jest](https://jestjs.io/) ## Únete al campus de programación de la comunidad ![https://mouredev.pro](./Images/pro.jpg) #### Te presento [mouredev pro](https://mouredev.pro), mi proyecto más importante para ayudarte a estudiar programación y desarrollo de software de manera diferente. > **¿Buscas un extra?** Aquí encontrarás este y otros cursos editados por lecciones individuales, para avanzar a tu ritmo y guardar el progreso. También dispondrás de ejercicios y correcciones, test para validar tus conocimientos, examen y certificado público de finalización, soporte, foro de estudiantes, reunionnes grupales, cursos exclusivos y mucho más. > > Entra en **[mouredev.pro](https://mouredev.pro)** y utiliza el cupón **"JAVASCRIPT"** con un 15% de descuento en tu primera suscripción. ## Preguntas frecuentes #### ¿Debo tener conocimientos previos? Mi idea es que el curso sea desde cero y para principiantes. Pensado para una persona que comienza por primera vez a programar. Es un curso de fundamentos, donde nos centraremos en aprender las bases del lenguaje con JavaScript puro (Vanilla JS). Esto no es un curso para aprender a desarrollar proyectos. Vamos a empezar desde el principio. Si la acogida de la comunidad es buena, seguiré creando cursos más avanzados. #### ¿Este curso se va a subir a YouTube? Sí, una vez finalizados, todos los cursos son editados y subidos en bloque a YouTube. #### ¿Existe algún lugar donde consultar dudas? He creado un canal llamado "JavaScript" en el [servidor de Discord](https://discord.gg/mouredev) de la comunidad. Allí puedes consultar dudas y ayudar al resto de miembros. Así nos beneficiamos tod@s. #### ¿Cómo puedo practicar? En cada lección encontrarás ejercicios para poner en práctica lo aprendido. También puedes realizar los ejercicios de mi web [retosdeprogramacion.com](https://retosdeprogramacion.com). ## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure. ### Freelance full-stack iOS & Android engineer [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1) [![Twitch Status](https://img.shields.io/twitch/status/mouredev?style=social)](https://twitch.com/mouredev) [![Discord](https://img.shields.io/discord/729672926432985098?style=social&label=Discord&logo=discord)](https://mouredev.com/discord) [![Twitter Follow](https://img.shields.io/twitter/follow/mouredev?style=social)](https://twitter.com/mouredev) ![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social) ![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social) Soy ingeniero de software desde 2010. Desde 2018 combino mi trabajo desarrollando Apps con la creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**. Si quieres unirte a nuestra comunidad de desarrollo, aprender programación, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en: [![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev) [![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) [![Pro](https://img.shields.io/badge/Cursos-mouredev.pro-FF5500?style=for-the-badge&logo=gnometerminal&logoColor=white&labelColor=101010)](https://mouredev.pro) [![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-14a1f0?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) [![Web](https://img.shields.io/badge/GitHub-MoureDev-087ec4?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev) ================================================ FILE: package.json ================================================ { "name": "hello_javascript", "version": "1.0.0", "description": "[![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-yellow?style=for-the-badge&logo=javascript&logoColor=white&labelColor=101010)](https://developer.mozilla.org/es/docs/Web/JavaScript) [![NodeJS](https://img.shields.io/badge/NODEJS-v20+-green?style=for-the-badge&logo=nodedotjs&logoColor=white&labelColor=101010)](https://nodejs.org/)", "main": "index.js", "scripts": { "test": "jest" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "jest": "^29.7.0" } }