From 3fe97a8e20d1796bc3c60a78bf32d4d439f16eb5 Mon Sep 17 00:00:00 2001
From: Stuart Taylor Click here to return home .*?<\\/p>\";/g), 'message: Your code should keep the double quotes around the entire string.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b85367417b2b2512b38",
- "title": "Catch Use of Assignment Operator Instead of Equality Operator",
- "description": [
- "Branching programs, i.e. ones that do different things if certain conditions are met, rely on Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Click here for cat photos. Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate: Things cats love: Top 3 things cats hate:
Don't worry - you've got this!",
- "",
- "@@STEP@@"
- ],
- "challengeSeed": [],
- "tests": [],
- "type": "Waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {
- "es": {
- "title": "Prepárate para nuestros Desafíos sobre Algoritmos",
- "description": [
- [
- "https://i.imgur.com/sJkp30a.png",
- "Una imagen de un desafio sobre algoritmos que presenta instrucciones, pruebas y el editor de código.",
- "Nuestros desafios sobre algoritmos te enseñarán como pensar como un programador.",
- ""
- ],
- [
- "https://i.imgur.com/d8LuRNh.png",
- "Una mamá pájaro saca un bebé pájaro fuer de su nido.",
- "Nuestros desafios anteriores te introdujeron a los conceptos de programación. Pero para estos desafios sobre algoritmos, ahora necesitarás aplicar lo que has aprendido y resolver problemas de respuesta abierta",
- ""
- ],
- [
- "https://i.imgur.com/WBetuBa.jpg",
- "Un programador frustado golpeando la pantalla de su computador.",
- "Nuestros desafíos sobre algortimos son difíciles. Algunos pueden requerir muchas horas para resolverse. Podrás frustarte, pero no te rindas.",
- ""
- ],
- [
- "https://i.imgur.com/p2TpOQd.jpg",
- "Un tierno perro que salta sobre un obstáculo, pica el ojo y te apunta con su pata.",
- "Cuando te atasques, usa la metodología Leer-Buscar-Preguntar.
No te preocupes - ya lo has entendido.",
- ""
- ]
- ]
- },
- "pt-br": {
- "title": "Prepare-se para nossos desafios de algoritmos",
- "description": [
- [
- "https://i.imgur.com/sJkp30a.png",
- "Uma imagem de um desafio de algoritmo mostrando instruções, testes e o editor de código.",
- "Nossos desafios de algoritmos vão te ensinar a pensar como um programador.",
- ""
- ],
- [
- "https://i.imgur.com/d8LuRNh.png",
- "Uma mãe pássaro expulsa seu filhote do ninho.",
- "Os desafios anteriores te apresentaram os conceitos de programação. Mas para esses desafios de algoritmos, você terá que aplicar o que aprendeu para resolver problemas abertos.",
- ""
- ],
- [
- "https://i.imgur.com/WBetuBa.jpg",
- "Um programador frustrado atravessando a tela de seu laptop com um soco.",
- "Os desafios de algoritmos são difíceis. Você pode levar várias horas para resolver alguns deles. Você vai ficar frustado. Mas não desista.",
- ""
- ],
- [
- "https://i.imgur.com/p2TpOQd.jpg",
- "Um cachorro fofo pulando sobre um obstáculo, piscando e apontando a pata na sua direção.",
- "Quando ficar travado, use a metodologia Ler-Pesquisar-Perguntar.
Não se preocupe - você consegue.",
- ""
- ]
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b3",
- "title": "Convert Celsius to Fahrenheit",
- "description": [
- "The algorithm to convert from Celsius to Fahrenheit is the temperature in Celsius times 9/5
, plus 32
.",
- "You are given a variable celsius
representing a temperature in Celsius. Use the variable fahrenheit
already defined and assign it the Fahrenheit temperature equivalent to the given Celsius temperature. Use the algorithm mentioned above to help convert the Celsius temperature to Fahrenheit.",
- "Don't worry too much about the function and return statements as they will be covered in future challenges. For now, only use operators that you have already learned."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function convertToF(celsius) {",
- " let fahrenheit;",
- " return fahrenheit;",
- "}",
- "",
- "convertToF(30);"
- ],
- "solutions": [
- "function convertToF(celsius) {\n let fahrenheit = celsius * 9/5 + 32;\n\n return fahrenheit;\n}\n\nconvertToF(30);\n"
- ],
- "tests": [
- "assert(typeof convertToF(0) === 'number', 'message: convertToF(0)
should return a number');",
- "assert(convertToF(-30) === -22, 'message: convertToF(-30)
should return a value of -22
');",
- "assert(convertToF(-10) === 14, 'message: convertToF(-10)
should return a value of 14
');",
- "assert(convertToF(0) === 32, 'message: convertToF(0)
should return a value of 32
');",
- "assert(convertToF(20) === 68, 'message: convertToF(20)
should return a value of 68
');",
- "assert(convertToF(30) === 86, 'message: convertToF(30)
should return a value of 86
');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "isRequired": true,
- "translations": {
- "es": {
- "title": "Convierte celsius a fahrenheit",
- "description": [
- "Para probar tu aprendizaje, crearás una solucion \"desde cero\". Coloca tu código entre las líneas indicadas y este será probado contra multiples casos de prueba.",
- "El algoritmo para convertir de Celsius a Fahrenheit consiste en multiplicar la temperatura en grados Celsius por 9/5 y al resultado agregarle 32.",
- "Se te da una variable celsius
representando una temperatura en Celsius. Crea una variable fahrenheit
y aplica el algoritmo para asignar la correspondiente temperatura en Fahrenheit."
- ]
- },
- "pt-br": {
- "title": "Converta Celsius para Fahrenheit",
- "description": [
- "O algoritmo para converter de Celsius para Fahrenheit é a temperatura em Celsius vezes 9/5
mais 32
.",
- "Você recebe uma variável celsius
representando uma temperatura em Celsius. Use a variável fahrenheit
já definida e aplique o algoritmo para atribuir a ela a temperatura correspondente em Fahrenheit."
- ]
- }
- }
- },
- {
- "id": "a202eed8fc186c8434cb6d61",
- "title": "Reverse a String",
- "description": [
- "Reverse the provided string.",
- "You may need to turn the string into an array before you can reverse it.",
- "Your result must be a string.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function reverseString(str) {",
- " return str;",
- "}",
- "",
- "reverseString(\"hello\");"
- ],
- "tests": [
- "assert(typeof reverseString(\"hello\") === \"string\", 'message: reverseString(\"hello\")
should return a string.');",
- "assert(reverseString(\"hello\") === \"olleh\", 'message: reverseString(\"hello\")
should become \"olleh\"
.');",
- "assert(reverseString(\"Howdy\") === \"ydwoH\", 'message: reverseString(\"Howdy\")
should become \"ydwoH\"
.');",
- "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", 'message: reverseString(\"Greetings from Earth\")
should return \"htraE morf sgniteerG\"
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function reverseString(str) {\n return str.split('').reverse().join('');\n}\n\nreverseString(\"hello\");\n"
- ],
- "MDNlinks": [
- "Global String Object",
- "String.prototype.split()",
- "Array.prototype.reverse()",
- "Array.prototype.join()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Invierte el texto",
- "description": [
- "Invierte la cadena de texto que se te provee",
- "Puede que necesites convertir la cadena de texto en un arreglo antes de que puedas invertirla",
- "El resultado debe ser una cadena de texto",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Inverta uma string",
- "description": [
- "Inverta a string fornecida.",
- "Talvez você tenha que transformar a string num array antes de invertê-la.",
- "Seu resultado deve ser uma string.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a302f7aae1aa3152a5b413bc",
- "title": "Factorialize a Number",
- "description": [
- "Return the factorial of the provided integer.",
- "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.",
- "Factorials are often represented with the shorthand notation n!
",
- "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120
",
- "Only integers greater than or equal to zero will be supplied to the function.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function factorialize(num) {",
- " return num;",
- "}",
- "",
- "factorialize(5);"
- ],
- "tests": [
- "assert(typeof factorialize(5) === 'number', 'message: factorialize(5)
should return a number.');",
- "assert(factorialize(5) === 120, 'message: factorialize(5)
should return 120.');",
- "assert(factorialize(10) === 3628800, 'message: factorialize(10)
should return 3628800.');",
- "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20)
should return 2432902008176640000.');",
- "assert(factorialize(0) === 1, 'message: factorialize(0)
should return 1.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function factorialize(num) {\n return num < 1 ? 1 : num * factorialize(num - 1);\n}\n\nfactorialize(5);\n"
- ],
- "MDNlinks": [
- "Arithmetic Operators"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Factoriza un número",
- "description": [
- "Crea una función que devuelva el factorial del número entero que se te provee",
- "El factorial de un número entero positivo n es la multiplicación de todos los enteros positivos menores o iguales a n",
- "Los factoriales son comúnmente representados con la notación n!
",
- "Por ejemplo: 5! = 1 * 2 * 3 * 4 * 5 = 120
",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Determine o fatorial de um número",
- "description": [
- "Retorne o fatorial do inteiro fornecido.",
- "Se o inteiro é representado pela letra n, o seu fatorial é o produto de todos os inteiros positivos menores ou iguais a n.",
- "Por exemplo: 5! = 1 * 2 * 3 * 4 * 5 = 120
",
- "Apenas inteiros maiores ou iguais a zero serão fornecidos à função.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a26cbbe9ad8655a977e1ceb5",
- "title": "Find the Longest Word in a String",
- "description": [
- "Return the length of the longest word in the provided sentence.",
- "Your response should be a number.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function findLongestWordLength(str) {",
- " return str.length;",
- "}",
- "",
- "findLongestWordLength(\"The quick brown fox jumped over the lazy dog\");"
- ],
- "tests": [
- "assert(typeof findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") === \"number\", 'message: findLongestWordLength(\"The quick brown fox jumped over the lazy dog\")
should return a number.');",
- "assert(findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") === 6, 'message: findLongestWordLength(\"The quick brown fox jumped over the lazy dog\")
should return 6.');",
- "assert(findLongestWordLength(\"May the force be with you\") === 5, 'message: findLongestWordLength(\"May the force be with you\")
should return 5.');",
- "assert(findLongestWordLength(\"Google do a barrel roll\") === 6, 'message: findLongestWordLength(\"Google do a barrel roll\")
should return 6.');",
- "assert(findLongestWordLength(\"What is the average airspeed velocity of an unladen swallow\") === 8, 'message: findLongestWordLength(\"What is the average airspeed velocity of an unladen swallow\")
should return 8.');",
- "assert(findLongestWordLength(\"What if we try a super-long word such as otorhinolaryngology\") === 19, 'message: findLongestWordLength(\"What if we try a super-long word such as otorhinolaryngology\")
should return 19.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function findLongestWordLength(str) {\n return str.split(' ').sort((a, b) => b.length - a.length)[0].length;\n}\n\nfindLongestWordLength(\"The quick brown fox jumped over the lazy dog\");\n"
- ],
- "MDNlinks": [
- "String.prototype.split()",
- "String.length"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Encuentra la palabra más larga",
- "description": [
- "Crea una función que devuelva la longitud de la palabra más larga en una frase dada",
- "El resultado debe ser un número",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Encontre a palavra mais longa de uma string",
- "description": [
- "Retorne o tamanho da palavra mais longa da frase fornecida.",
- "Sua resposta deve ser um número.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a789b3483989747d63b0e427",
- "title": "Return Largest Numbers in Arrays",
- "description": [
- "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.",
- "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i]
.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function largestOfFour(arr) {",
- " // You can do this!",
- " return arr;",
- "}",
- "",
- "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);"
- ],
- "tests": [
- "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'message: largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])
should return an array.');",
- "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27, 5, 39, 1001], 'message: largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]])
should return [27, 5, 39, 1001]
.');",
- "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9, 35, 97, 1000000], 'message: largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]])
should return [9, 35, 97, 1000000]
.');",
- "assert.deepEqual(largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]]), [25, 48, 21, -3], 'message: largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]])
should return [25, 48, 21, -3]
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function largestOfFour(arr) {\n return arr.map(subArr => Math.max.apply(null, subArr));\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);\n"
- ],
- "MDNlinks": [
- "Comparison Operators"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Devuelve el mayor entero de cada arreglo",
- "description": [
- "Crea una función que devuelva un arreglo que contenga el mayor de los números de cada sub-arreglo que recibe. Para simplificar las cosas, el arreglo que recibirá tendrá exactamente 4 sub-arreglos",
- "Recuerda que puedes iterar a través de un arreglo con un búcle simple, y acceder a cada miembro utilizando la sintaxis arr[i].",
- "Si escribes tu propio test con Chai.js, asegúrate de utilizar un operador de igualdad estricto en lugar de un operador de igualdad cuando compares arreglos. ",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Retorne os maiores números de arrays",
- "description": [
- "Retorne um array contendo o maior número de cada sub-array fornecido. Para simplificar, o array fornecido conterá exatamente 4 sub-arrays.",
- "Lembre-se, você pode iterar por um array com um simples for
e acessar cada membro do array com a sintaxe arr[i]
.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "acda2fb1324d9b0fa741e6b5",
- "title": "Confirm the Ending",
- "description": [
- "Check if a string (first argument, str
) ends with the given target string (second argument, target
).",
- "This challenge can be solved with the .endsWith()
method, which was introduced in ES2015. But for the purpose of this challenge, we would like you to use one of the JavaScript substring methods instead.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function confirmEnding(str, target) {",
- " // \"Never give up and good luck will find you.\"",
- " // -- Falcor",
- " return str;",
- "}",
- "",
- "confirmEnding(\"Bastian\", \"n\");"
- ],
- "tests": [
- "assert(confirmEnding(\"Bastian\", \"n\") === true, 'message: confirmEnding(\"Bastian\", \"n\")
should return true.');",
- "assert(confirmEnding(\"Congratulation\", \"on\") === true, 'message: confirmEnding(\"Congratulation\", \"on\")
should return true.');",
- "assert(confirmEnding(\"Connor\", \"n\") === false, 'message: confirmEnding(\"Connor\", \"n\")
should return false.');",
- "assert(confirmEnding(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") === false, 'message: confirmEnding(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\")
should return false.');",
- "assert(confirmEnding(\"He has to give me a new name\", \"name\") === true, 'message: confirmEnding(\"He has to give me a new name\", \"name\")
should return true.');",
- "assert(confirmEnding(\"Open sesame\", \"same\") === true, 'message: confirmEnding(\"Open sesame\", \"same\")
should return true.');",
- "assert(confirmEnding(\"Open sesame\", \"pen\") === false, 'message: confirmEnding(\"Open sesame\", \"pen\")
should return false.');",
- "assert(confirmEnding(\"Open sesame\", \"game\") === false, 'message: confirmEnding(\"Open sesame\", \"game\")
should return false.');",
- "assert(confirmEnding(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: confirmEnding(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")
should return false.');",
- "assert(confirmEnding(\"Abstraction\", \"action\") === true, 'message: confirmEnding(\"Abstraction\", \"action\")
should return true.');",
- "assert(!(/\\.endsWith\\(.*?\\)\\s*?;?/.test(code)) && !(/\\['endsWith'\\]/.test(code)), 'message: Do not use the built-in method .endsWith()
to solve the challenge.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function confirmEnding(str, target) {\n return str.substring(str.length - target.length) === target;\n}\n\nconfirmEnding(\"Bastian\", \"n\");\n"
- ],
- "MDNlinks": [
- "String.prototype.substr()",
- "String.prototype.substring()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Confirma la terminación",
- "description": [
- "Verifica si una cadena de texto (primer argumento) termina con otra cadena de texto (segundo argumento).",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Confirme o final",
- "description": [
- "Verifique se uma string (primeiro argumento, str
) termina com a string alvo fornecida (segundo argumento, target
).",
- "Esse desafio pode ser resolvido com o método .endsWith()
, que foi introduzido na ES2015. Mas para o propósito desse desafio, nós gostaríamos que, ao invés dele, você usasse algum dos métodos de substring do JavaScript.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "afcc8d540bea9ea2669306b6",
- "title": "Repeat a String Repeat a String",
- "description": [
- "Repeat a given string str
(first argument) for num
times (second argument). Return an empty string if num
is not a positive number.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function repeatStringNumTimes(str, num) {",
- " // repeat after me",
- " return str;",
- "}",
- "",
- "repeatStringNumTimes(\"abc\", 3);"
- ],
- "tests": [
- "assert(repeatStringNumTimes(\"*\", 3) === \"***\", 'message: repeatStringNumTimes(\"*\", 3)
should return \"***\"
.');",
- "assert(repeatStringNumTimes(\"abc\", 3) === \"abcabcabc\", 'message: repeatStringNumTimes(\"abc\", 3)
should return \"abcabcabc\"
.');",
- "assert(repeatStringNumTimes(\"abc\", 4) === \"abcabcabcabc\", 'message: repeatStringNumTimes(\"abc\", 4)
should return \"abcabcabcabc\"
.');",
- "assert(repeatStringNumTimes(\"abc\", 1) === \"abc\", 'message: repeatStringNumTimes(\"abc\", 1)
should return \"abc\"
.');",
- "assert(repeatStringNumTimes(\"*\", 8) === \"********\", 'message: repeatStringNumTimes(\"*\", 8)
should return \"********\"
.');",
- "assert(repeatStringNumTimes(\"abc\", -2) === \"\", 'message: repeatStringNumTimes(\"abc\", -2)
should return \"\"
.');",
- "assert(!/\\.repeat/g.test(code), 'message: The built-in repeat()
-method should not be used');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function repeatStringNumTimes(str, num) {\n if (num < 0) return '';\n return num === 1 ? str : str + repeatStringNumTimes(str, num-1);\n}\n\nrepeatStringNumTimes(\"abc\", 3);\n"
- ],
- "MDNlinks": [
- "Global String Object"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Repite el Texto Repite el Texto",
- "description": [
- "Repite una cadena de texto dada (primer argumento) num
veces (segundo argumento). Retorna una cadena de texto vacía si num
es un número negativo.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Repita uma string Repita uma string",
- "description": [
- "Repita uma string str
dada (primeiro argumento) num
vezes (segundo argumento). Retorne uma string vazia se num
não for um número positivo.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "ac6993d51946422351508a41",
- "title": "Truncate a String",
- "description": [
- "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a ...
ending.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function truncateString(str, num) {",
- " // Clear out that junk in your trunk",
- " return str;",
- "}",
- "",
- "truncateString(\"A-tisket a-tasket A green and yellow basket\", 8);"
- ],
- "tests": [
- "assert(truncateString(\"A-tisket a-tasket A green and yellow basket\", 8) === \"A-tisket...\", 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", 8)
should return \"A-tisket...\".');",
- "assert(truncateString(\"Peter Piper picked a peck of pickled peppers\", 11) === \"Peter Piper...\", 'message: truncateString(\"Peter Piper picked a peck of pickled peppers\", 11)
should return \"Peter Piper...\".');",
- "assert(truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length)
should return \"A-tisket a-tasket A green and yellow basket\".');",
- "assert(truncateString('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2)
should return \"A-tisket a-tasket A green and yellow basket\".');",
- "assert(truncateString(\"A-\", 1) === \"A...\", 'message: truncateString(\"A-\", 1)
should return \"A...\".');",
- "assert(truncateString(\"Absolutely Longer\", 2) === \"Ab...\", 'message: truncateString(\"Absolutely Longer\", 2)
should return \"Ab...\".');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function truncateString(str, num) {\n if (num >= str.length) {\n return str;\n }\n\n return str.slice(0, num) + '...';\n}\n\ntruncateString(\"A-tisket a-tasket A green and yellow basket\", 8);\n"
- ],
- "MDNlinks": [
- "String.prototype.slice()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Trunca una Cadena de Texto",
- "description": [
- "Trunca una cadena de texto (primer argumento) si su longitud es mayor que un máximo de caracteres dado (segundo argumento). Devuelve la cadena de texto truncada con una terminación \"...\".",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Trunque uma string",
- "description": [
- "Trunque uma string (primeiro argumento) se ela for mais longa do que o comprimento máximo dado (segundo argumento). Retorne a string truncada com um ...
no final.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a6e40f1041b06c996f7b2406",
- "title": "Finders Keepers",
- "description": [
- "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument). If no element passes the test, return undefined.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function findElement(arr, func) {",
- " let num = 0;",
- " return num;",
- "}",
- "",
- "findElement([1, 2, 3, 4], num => num % 2 === 0);"
- ],
- "solutions": [
- "function findElement(arr, func) {\n let num;\n\n arr.some(e => {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n\n return num;\n}\n\nfindElement([1, 2, 3, 4], num => num % 2 === 0);\n"
- ],
- "tests": [
- "assert.strictEqual(findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'message: findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; })
should return 8.');",
- "assert.strictEqual(findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; })
should return undefined.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Array.prototype.filter()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Buscando la verdad",
- "description": [
- "Crea una función que busque dentro de un vector (primer argumento) y que devuelva el primer elemento que pase una prueba de verdad (segundo argumento).",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Achado não é roubado",
- "description": [
- "Crie uma função que itera sobre um array (primeiro argumento) e retorna o primeiro elemento do array que retornar true
para uma função de teste (segundo argumento). Se nenhum elemento passar no teste, retorne undefined
.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- },
- "fr": {
- "title": "Détecteur de mensonges",
- "description": [
- "Crée une fonction qui parcourt un tableau (premier argument) et renvoie le premier élément du tableau qui passe le test (second argument).",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a77dbc43c33f39daa4429b4f",
- "title": "Boo who",
- "description": [
- "Check if a value is classified as a boolean primitive. Return true or false.",
- "Boolean primitives are true and false.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function booWho(bool) {",
- " // What is the new fad diet for ghost developers? The Boolean.",
- " return bool;",
- "}",
- "",
- "booWho(null);"
- ],
- "solutions": [
- "function booWho(bool) {\n return typeof bool === \"boolean\";\n}\n\nbooWho(null);"
- ],
- "tests": [
- "assert.strictEqual(booWho(true), true, 'message: booWho(true)
should return true.');",
- "assert.strictEqual(booWho(false), true, 'message: booWho(false)
should return true.');",
- "assert.strictEqual(booWho([1, 2, 3]), false, 'message: booWho([1, 2, 3])
should return false.');",
- "assert.strictEqual(booWho([].slice), false, 'message: booWho([].slice)
should return false.');",
- "assert.strictEqual(booWho({ \"a\": 1 }), false, 'message: booWho({ \"a\": 1 })
should return false.');",
- "assert.strictEqual(booWho(1), false, 'message: booWho(1)
should return false.');",
- "assert.strictEqual(booWho(NaN), false, 'message: booWho(NaN)
should return false.');",
- "assert.strictEqual(booWho(\"a\"), false, 'message: booWho(\"a\")
should return false.');",
- "assert.strictEqual(booWho(\"true\"), false, 'message: booWho(\"true\")
should return false.');",
- "assert.strictEqual(booWho(\"false\"), false, 'message: booWho(\"false\")
should return false.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Boolean Objects"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "¡Bu!",
- "description": [
- "Crea una función que verifique si el valor que se le pasa es de tipo booleano. Haz que la función devuelva true o false según corresponda.",
- "Los primitivos booleanos primitivos son: true y false",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Bu!",
- "description": [
- "Verifique se um valor é classificado como um primitivo booleano. Retorne true
ou false
.",
- "Primitivos booleanos são true
e false
.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Tente programar em par. Escreva seu próprio código."
- ]
- },
- "fr": {
- "title": "Boo !",
- "description": [
- "Crée une fonction qui vérifie qu'une valeur est de type booléen. Renvoie true ou false.",
- "Les primitives booléennes sont true ou false.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "ab6137d4e35944e21037b769",
- "title": "Title Case a Sentence",
- "description": [
- "Return the provided string with the first letter of each word capitalized. Make sure the rest of the word is in lower case.",
- "For the purpose of this exercise, you should also capitalize connecting words like \"the\" and \"of\".",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function titleCase(str) {",
- " return str;",
- "}",
- "",
- "titleCase(\"I'm a little tea pot\");"
- ],
- "tests": [
- "assert(typeof titleCase(\"I'm a little tea pot\") === \"string\", 'message: titleCase(\"I'm a little tea pot\")
should return a string.');",
- "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: titleCase(\"I'm a little tea pot\")
should return I'm A Little Tea Pot
.');",
- "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: titleCase(\"sHoRt AnD sToUt\")
should return Short And Stout
.');",
- "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")
should return Here Is My Handle Here Is My Spout
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function titleCase(str) {\n return str.split(' ').map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase()).join(' ');\n}\n\ntitleCase(\"I'm a little tea pot\");\n"
- ],
- "MDNlinks": [
- "String.prototype.split()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Aplica formato de título",
- "description": [
- "Crea una función que devuelva la cadena de texto que recibe con la primera letra de cada palabra en mayúscula. Asegúrate de que el resto de las letras sean minúsculas",
- "Para este ejercicio, también debes poner en mayúscula conectores como \"the\" y \"of\".",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Transforme Uma String Num Título",
- "description": [
- "Retorne a string fornecida com a primeira letra de cada palavra em maiúsculo. Certifique-se de que o resto da palavra esteja minúsculo.",
- "Para o propósito desse exercício, você também deve deixar maiúscula a primeira letra das palavras de ligação como \"the\" e \"of\".",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "579e2a2c335b9d72dd32e05c",
- "title": "Slice and Splice",
- "description": [
- "You are given two arrays and an index.",
- "Use the array methods slice
and splice
to copy each element of the first array into the second array, in order.",
- "Begin inserting elements at index n
of the second array.",
- "Return the resulting array. The input arrays should remain the same after the function runs.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function frankenSplice(arr1, arr2, n) {",
- " // It's alive. It's alive!",
- " return arr2;",
- "}",
- "",
- "frankenSplice([1, 2, 3], [4, 5, 6], 1);"
- ],
- "tail": [
- "let testArr1 = [1, 2];",
- "let testArr2 = [\"a\", \"b\"];"
- ],
- "tests": [
- "assert.deepEqual(frankenSplice([1, 2, 3], [4, 5], 1), [4, 1, 2, 3, 5], 'message: frankenSplice([1, 2, 3], [4, 5], 1)
should return [4, 1, 2, 3, 5]
.');",
- "assert.deepEqual(frankenSplice(testArr1, testArr2, 1), [\"a\", 1, 2, \"b\"], 'message: frankenSplice([1, 2], [\"a\", \"b\"], 1)
should return [\"a\", 1, 2, \"b\"]
.');",
- "assert.deepEqual(frankenSplice([\"claw\", \"tentacle\"], [\"head\", \"shoulders\", \"knees\", \"toes\"], 2), [\"head\", \"shoulders\", \"claw\", \"tentacle\", \"knees\", \"toes\"], 'message: frankenSplice([\"claw\", \"tentacle\"], [\"head\", \"shoulders\", \"knees\", \"toes\"], 2)
should return [\"head\", \"shoulders\", \"claw\", \"tentacle\", \"knees\", \"toes\"]
.');",
- "assert.deepEqual(frankenSplice([1, 2, 3, 4], [], 0), [1, 2, 3, 4], 'message: All elements from the first array should be added to the second array in their original order.');",
- "assert(testArr1[0] === 1 && testArr1[1] === 2, 'message: The first array should remain the same after the function runs.');",
- "assert(testArr2[0] === \"a\" && testArr2[1] === \"b\", 'message: The second array should remain the same after the function runs.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "isBeta": true,
- "solutions": [
- "function frankenSplice(arr1, arr2, n) {\n // It's alive. It's alive!\n let result = arr2.slice();\n for (let i = 0; i < arr1.length; i++) {\n result.splice(n+i, 0, arr1[i]);\n }\n return result;\n}\n\nfrankenSplice([1, 2, 3], [4, 5], 1);\n"
- ],
- "MDNlinks": [
- "Array.prototype.slice()",
- "Array.prototype.splice()"
- ],
- "challengeType": 5,
- "translations": {
- "pt-br": {
- "title": "Slice e splice",
- "description": [
- "Você recebe dois arrays e um índice.",
- "Use os métodos de array slice
e splice
para copiar cada elemento do primeiro array para o segundo array, em ordem.",
- "Comece a inserir elementos no índice n
do segundo array.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "adf08ec01beb4f99fc7a68f2",
- "title": "Falsy Bouncer",
- "description": [
- "Remove all falsy values from an array.",
- "Falsy values in JavaScript are false
, null
, 0
, \"\"
, undefined
, and NaN
.",
- "Hint: Try converting each value to a Boolean.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function bouncer(arr) {",
- " // Don't show a false ID to this bouncer.",
- " return arr;",
- "}",
- "",
- "bouncer([7, \"ate\", \"\", false, 9]);"
- ],
- "tests": [
- "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: bouncer([7, \"ate\", \"\", false, 9])
should return [7, \"ate\", 9]
.');",
- "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: bouncer([\"a\", \"b\", \"c\"])
should return [\"a\", \"b\", \"c\"]
.');",
- "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, \"\"]), [], 'message: bouncer([false, null, 0, NaN, undefined, \"\"])
should return []
.');",
- "assert.deepEqual(bouncer([1, null, NaN, 2, undefined]), [1, 2], 'message: bouncer([1, null, NaN, 2, undefined])
should return [1, 2]
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function bouncer(arr) {\n return arr.filter(e => e);\n}\n\nbouncer([7, \"ate\", \"\", false, 9]);\n"
- ],
- "MDNlinks": [
- "Boolean Objects",
- "Array.prototype.filter()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Detector de Mentiras",
- "description": [
- "Remueve todos los valores falsy de un arreglo dado",
- "En JavaScript, los valores falsy son los siguientes: false
, null
, 0
, \"\"
, undefined
, y NaN
.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Detector de mentiras",
- "description": [
- "Remova todos os valores falsos de um array.",
- "Valores falsos em JavaScript são false
, null
, 0
, \"\"
, undefined
e NaN
.",
- "Dica: Tente converter cada valor para um booleano.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a24c1a4622e3c05097f71d67",
- "title": "Where do I Belong",
- "description": [
- "Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted. The returned value should be a number.",
- "For example, getIndexToIns([1,2,3,4], 1.5)
should return 1
because it is greater than 1
(index 0), but less than 2
(index 1).",
- "Likewise, getIndexToIns([20,3,5], 19)
should return 2
because once the array has been sorted it will look like [3,5,20]
and 19
is less than 20
(index 2) and greater than 5
(index 1).",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function getIndexToIns(arr, num) {",
- " // Find my place in this sorted array.",
- " return num;",
- "}",
- "",
- "getIndexToIns([40, 60], 50);"
- ],
- "tests": [
- "assert(getIndexToIns([10, 20, 30, 40, 50], 35) === 3, 'message: getIndexToIns([10, 20, 30, 40, 50], 35)
should return 3
.');",
- "assert(typeof(getIndexToIns([10, 20, 30, 40, 50], 35)) === \"number\", 'message: getIndexToIns([10, 20, 30, 40, 50], 35)
should return a number.');",
- "assert(getIndexToIns([10, 20, 30, 40, 50], 30) === 2, 'message: getIndexToIns([10, 20, 30, 40, 50], 30)
should return 2
.');",
- "assert(typeof(getIndexToIns([10, 20, 30, 40, 50], 30)) === \"number\", 'message: getIndexToIns([10, 20, 30, 40, 50], 30)
should return a number.');",
- "assert(getIndexToIns([40, 60], 50) === 1, 'message: getIndexToIns([40, 60], 50)
should return 1
.');",
- "assert(typeof(getIndexToIns([40, 60], 50)) === \"number\", 'message: getIndexToIns([40, 60], 50)
should return a number.');",
- "assert(getIndexToIns([3, 10, 5], 3) === 0, 'message: getIndexToIns([3, 10, 5], 3)
should return 0
.');",
- "assert(typeof(getIndexToIns([3, 10, 5], 3)) === \"number\", 'message: getIndexToIns([3, 10, 5], 3)
should return a number.');",
- "assert(getIndexToIns([5, 3, 20, 3], 5) === 2, 'message: getIndexToIns([5, 3, 20, 3], 5)
should return 2
.');",
- "assert(typeof(getIndexToIns([5, 3, 20, 3], 5)) === \"number\", 'message: getIndexToIns([5, 3, 20, 3], 5)
should return a number.');",
- "assert(getIndexToIns([2, 20, 10], 19) === 2, 'message: getIndexToIns([2, 20, 10], 19)
should return 2
.');",
- "assert(typeof(getIndexToIns([2, 20, 10], 19)) === \"number\", 'message: getIndexToIns([2, 20, 10], 19)
should return a number.');",
- "assert(getIndexToIns([2, 5, 10], 15) === 3, 'message: getIndexToIns([2, 5, 10], 15)
should return 3
.');",
- "assert(typeof(getIndexToIns([2, 5, 10], 15)) === \"number\", 'message: getIndexToIns([2, 5, 10], 15)
should return a number.');",
- "assert(getIndexToIns([], 1) === 0, 'message: getIndexToIns([], 1)
should return 0
.');",
- "assert(typeof(getIndexToIns([], 1)) === \"number\", 'message: getIndexToIns([], 1)
should return a number.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function getIndexToIns(arr, num) {\n arr = arr.sort((a, b) => a - b);\n\n for (let i = 0; i < arr.length; i++) {\n if (arr[i] >= num) {\n return i;\n }\n }\n\n return arr.length;\n}\n\ngetIndexToIns([40, 60], 50);\n"
- ],
- "MDNlinks": [
- "Array.prototype.sort()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "¿Cuál es mi Asiento?",
- "description": [
- "Devuelve el menor índice en el que un valor (segundo argumento) debe ser insertado en un arreglo (primer argumento) una vez ha sido ordenado.",
- "Por ejemplo, where([1,2,3,4], 1.5) debe devolver 1 porque el segundo argumento de la función (1.5) es mayor que 1 (con índice 0 en el arreglo), pero menor que 2 (con índice 1).",
- "Mientras que where([20,3,5], 19)
debe devolver 2
porque una vez ordenado el arreglo se verá com [3,5,20]
y 19
es menor que 20
(índice 2) y mayor que 5
(índice 1).",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Onde é meu lugar?",
- "description": [
- "Retorne o menor índice no qual um valor (segundo argumento) deve ser inserido num array (primeiro argumento) depois que ele foi ordenado. O valor retornado deve ser um número.",
- "Por exemplo, getIndexToIns([1,2,3,4], 1.5)
deve retornar 1
porque 1.5
é maior que 1
(índice 0), mas menor que 2
(índice 1).",
- "Da mesma forma, getIndexToIns([20,3,5], 19)
deve retornar 2
porque, depois de ordenado, o array será [3,5,20]
e 19
é menor que 20
(índice 2) e maior que 5
(index 1).",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "af2170cad53daa0770fabdea",
- "title": "Mutations",
- "description": [
- "Return true if the string in the first element of the array contains all of the letters of the string in the second element of the array.",
- "For example, [\"hello\", \"Hello\"]
, should return true because all of the letters in the second string are present in the first, ignoring case.",
- "The arguments [\"hello\", \"hey\"]
should return false because the string \"hello\" does not contain a \"y\".",
- "Lastly, [\"Alien\", \"line\"]
, should return true because all of the letters in \"line\" are present in \"Alien\".",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function mutation(arr) {",
- " return arr;",
- "}",
- "",
- "mutation([\"hello\", \"hey\"]);"
- ],
- "tests": [
- "assert(mutation([\"hello\", \"hey\"]) === false, 'message: mutation([\"hello\", \"hey\"])
should return false.');",
- "assert(mutation([\"hello\", \"Hello\"]) === true, 'message: mutation([\"hello\", \"Hello\"])
should return true.');",
- "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, 'message: mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"])
should return true.');",
- "assert(mutation([\"Mary\", \"Army\"]) === true, 'message: mutation([\"Mary\", \"Army\"])
should return true.');",
- "assert(mutation([\"Mary\", \"Aarmy\"]) === true, 'message: mutation([\"Mary\", \"Aarmy\"])
should return true.');",
- "assert(mutation([\"Alien\", \"line\"]) === true, 'message: mutation([\"Alien\", \"line\"])
should return true.');",
- "assert(mutation([\"floor\", \"for\"]) === true, 'message: mutation([\"floor\", \"for\"])
should return true.');",
- "assert(mutation([\"hello\", \"neo\"]) === false, 'message: mutation([\"hello\", \"neo\"])
should return false.');",
- "assert(mutation([\"voodoo\", \"no\"]) === false, 'message: mutation([\"voodoo\", \"no\"])
should return false.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function mutation(arr) {\n let hash = Object.create(null);\n\n arr[0].toLowerCase().split('').forEach(c => hash[c] = true);\n\n return !arr[1].toLowerCase().split('').filter(c => !hash[c]).length;\n}\n\nmutation([\"hello\", \"hey\"]);\n"
- ],
- "MDNlinks": [
- "String.prototype.indexOf()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Mutaciones",
- "description": [
- "Crea una función que devuelva true
si la cadena de texto del primer elemento de un arreglo contiene todas las letras de la cadena de texto del segundo elemento del arreglo.",
- "Por ejemplo, [\"hello\", \"Hello\"]
, debe devolver true
porque todas las letras en la segunda cadena de texto están presentes en la primera, sin distinguir entre mayúsculas y minúsculas.",
- "En el caso de [\"hello\", \"hey\"]
la función debe devolver false porque la cadena de texto \"hello\" no contiene una \"y\".",
- "Finalmente, [\"Alien\", \"line\"]
, la función debe devolver true
porque todas las letras en \"line\" están presentes en \"Alien\".",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Mutações",
- "description": [
- "Retorne true
se a string no primeiro elemento do array contiver todas as letras da string no segundo elemento do array.",
- "Por exemplo, para os argumentos [\"hello\", \"Hello\"]
, sua função deve retornar true
, porque todas as letras da segunda string estão presentes na primeira, ignorando maiúsculas e minúsculas.",
- "Para os argumentos [\"hello\", \"hey\"]
, sua função deve retornar false
porque a string \"hello\" não contém um \"y\".",
- "Finalmente, para [\"Alien\", \"line\"]
, sua função deve retornar true
porque todas as letras em \"line\" estão presentes em \"Alien\".",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a9bd25c716030ec90084d8a1",
- "title": "Chunky Monkey",
- "description": [
- "Write a function that splits an array (first argument) into groups the length of size
(second argument) and returns them as a two-dimensional array.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function chunkArrayInGroups(arr, size) {",
- " // Break it up.",
- " return arr;",
- "}",
- "",
- "chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2);"
- ],
- "tests": [
- "assert.deepEqual(chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2)
should return [[\"a\", \"b\"], [\"c\", \"d\"]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3)
should return [[0, 1, 2], [3, 4, 5]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 2)
should return [[0, 1], [2, 3], [4, 5]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 4)
should return [[0, 1, 2, 3], [4, 5]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3), [[0, 1, 2], [3, 4, 5], [6]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3)
should return [[0, 1, 2], [3, 4, 5], [6]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4), [[0, 1, 2, 3], [4, 5, 6, 7], [8]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4)
should return [[0, 1, 2, 3], [4, 5, 6, 7], [8]]
.');",
- "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2), [[0, 1], [2, 3], [4, 5], [6, 7], [8]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2)
should return [[0, 1], [2, 3], [4, 5], [6, 7], [8]]
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function chunkArrayInGroups(arr, size) {\n let out = [];\n\n for (let i = 0; i < arr.length; i += size) {\n out.push(arr.slice(i, i + size));\n }\n\n return out;\n}\n\nchunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2);\n"
- ],
- "MDNlinks": [
- "Array.prototype.push()",
- "Array.prototype.slice()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "En mil Pedazos",
- "description": [
- "Escribe una función que parta un arreglo (primer argumento) en fragmentos de una longitud dada (segundo argumento) y los devuelva en forma de un arreglo bidimensional.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Em pedaços",
- "description": [
- "Escreva uma função que divide um array (primeiro argumento) em grupos de comprimento size
(segundo argumento) e retorna esses grupos num array bidimensional.",
- "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código."
- ]
- }
- }
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json
deleted file mode 100644
index 3694741c81..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json
+++ /dev/null
@@ -1,822 +0,0 @@
-{
- "name": "Basic Data Structures",
- "order": 5,
- "time": "1 hour",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "5a61985d9bb0a3540e49dc9f",
- "title": "Introduction to Arrays",
- "description": [
- "",
- "",
- "Arrays are one of JavaScript's most fundamental built-in data structures, and probably the data structure that you will work with most often throughout the course of the freeCodeCamp curriculum. The array is by no means unique to JavaScript, however — in fact, it’s probably safe to say that arrays are utilized by almost every complex program... ever.
In computer science, an array is a linear collection of elements characterized by the fact that each element has a unique index, or address, that can be computed and used to look up an element's position at run-time.",
- "",
- "@@STEP@@",
- "",
- "",
- "In JavaScript, arrays are written as comma-separated lists and are enclosed in brackets [element1, element2, element3]
. They can be any length, and store any type of data supported by JavaScript.
Arrays can sometimes be simple and serve very basic functionalities, but they can also be complex and very powerful - all of which depends on how the programmer chooses to utilize them
From this point forward, whenever we refer to the term array, it will be strictly within the context of JavaScript.",
- "",
- "@@STEP@@",
- "",
- "",
- "JavaScript offers many array methods, which are a sort of built in function, that allow us to access, traverse, and mutate arrays as needed, depending on our purpose.
In the coming challenges, we will discuss several of the most common and useful methods, and a few other key techniques, that will help you to better understand and utilize arrays as data structures in JavaScript.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7b7e367417b2b2512b20",
- "title": "Use an Array to Store a Collection of Data",
- "description": [
- "The below is an example of the simplest implementation of an array data structure. This is known as a one-dimensional array, meaning it only has one level, or that it does not have any other arrays nested within it. Notice it contains booleans, strings, and numbers, among other valid JavaScript data types:",
- "let simpleArray = ['one', 2, 'three’, true, false, undefined, null];
",
- "All array's have a length property, which as shown above, can be very easily accessed with the syntax
console.log(simpleArray.length);
// logs 7Array.length
.",
- "A more complex implementation of an array can be seen below. This is known as a multi-dimensional array, or an array that contains other arrays. Notice that this array also contains JavaScript objects, which we will examine very closely in our next section, but for now, all you need to know is that arrays are also capable of storing complex objects.",
- "let complexArray = [
",
- "
[
{
one: 1,
two: 2
},
{
three: 3,
four: 4
}
],
[
{
a: \"a\",
b: \"b\"
},
{
c: \"c\",
d: “d”
}
]
];
",
- "We have defined a variable called yourArray
. Complete the statement by assigning an array of at least 5 elements in length to the yourArray
variable. Your array should contain at least one string, one number, and one boolean."
- ],
- "challengeSeed": [
- "let yourArray; // change this line"
- ],
- "tests": [
- "assert.strictEqual(Array.isArray(yourArray), true, 'message: yourArray is an array');",
- "assert.isAtLeast(yourArray.length, 5, 'message: yourArray
is at least 5 elements long');",
- "assert(yourArray.filter( el => typeof el === 'boolean').length >= 1, 'message: yourArray
contains at least one boolean
');",
- "assert(yourArray.filter( el => typeof el === 'number').length >= 1, 'message: yourArray
contains at least one number
');",
- "assert(yourArray.filter( el => typeof el === 'string').length >= 1, 'message: yourArray
contains at least one string
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "5a661e0f1068aca922b3ef17",
- "title": "Access an Array's Contents Using Bracket Notation",
- "description": [
- "The fundamental feature of any data structure is, of course, the ability to not only store data, but to be able to retrieve that data on command. So, now that we've learned how to create an array, let's begin to think about how we can access that array's information.",
- "When we define a simple array as seen below, there are 3 items in it:",
- "let ourArray = [\"a\", \"b\", \"c\"];
",
- "In an array, each array item has an index. This index doubles as the position of that item in the array, and how you reference it. However, it is important to note, that JavaScript arrays are zero-indexed, meaning that the first element of an array is actually at the zeroth position, not the first.",
- "In order to retrieve an element from an array we can enclose an index in brackets and append it to the end of an array, or more commonly, to a variable which references an array object. This is known as bracket notation.",
- "For example, if we want to retrieve the \"a\"
from ourArray
and assign it to a variable, we can do so with the following code:",
- "let ourVariable = ourArray[0];
",
- "In addition to accessing the value associated with an index, you can also set an index to a value using the same notation:",
- "
// ourVariable equals \"a\"ourArray[1] = \"not b anymore\";
",
- "Using bracket notation, we have now reset the item at index 1 from
// ourArray now equals [\"a\", \"not b anymore\", \"c\"];\"b\"
, to \"not b anymore\"
.",
- "
",
- "In order to complete this challenge, set the 2nd position (index 1
) of myArray
to anything you want, besides \"b\"
."
- ],
- "challengeSeed": [
- "let myArray = [\"a\", \"b\", \"c\", \"d\"];",
- "// change code below this line",
- "",
- "//change code above this line",
- "console.log(myArray);"
- ],
- "tests": [
- "assert.strictEqual(myArray[0], \"a\", 'message: myArray[0]
is equal to \"a\"
');",
- "assert.notStrictEqual(myArray[1], \"b\", 'message: myArray[1]
is no longer set to \"b\"
');",
- "assert.strictEqual(myArray[2], \"c\", 'message: myArray[2]
is equal to \"c\"
');",
- "assert.strictEqual(myArray[3], \"d\", 'message: myArray[3]
is equal to \"d\"
');"
- ],
- "type": "waypoint",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d78b2367417b2b2512b0e",
- "title": "Add Items to an Array with push() and unshift()",
- "description": [
- "An array's length, like the data types it can contain, is not fixed. Arrays can be defined with a length of any number of elements, and elements can be added or removed over time; in other words, arrays are mutable. In this challenge, we will look at two methods with which we can programmatically modify an array: Array.push()
and Array.unshift()
. ",
- "Both methods take one or more elements as parameters and add those elements to the array the method is being called on; the push()
method adds elements to the end of an array, and unshift()
adds elements to the beginning. Consider the following:",
- "let twentyThree = 'XXIII';
let romanNumerals = ['XXI', 'XXII'];
romanNumerals.unshift('XIX', 'XX');
// now equals ['XIX', 'XX', 'XXI', 'XXII']
romanNumerals.push(twentyThree);
// now equals ['XIX', 'XX', 'XXI', 'XXII', 'XXIII']",
- "Notice that we can also pass variables, which allows us even greater flexibility in dynamically modifying our array's data.",
- "
",
- "We have defined a function, mixedNumbers
, which we are passing an array as an argument. Modify the function by using push()
and unshift()
to add 'I', 2, 'three'
to the beginning of the array and 7, 'VIII', 9
to the end so that the returned array contains representations of the numbers 1-9 in order."
- ],
- "challengeSeed": [
- "function mixedNumbers(arr) {",
- " // change code below this line",
- "",
- " // change code above this line",
- " return arr;",
- "}",
- "",
- "// do not change code below this line",
- "console.log(mixedNumbers(['IV', 5, 'six']));"
- ],
- "tests": [
- "assert.deepEqual(mixedNumbers(['IV', 5, 'six']), ['I', 2, 'three', 'IV', 5, 'six', 7, 'VIII', 9], 'message: mixedNumbers([\"IV\", 5, \"six\"])
should now return [\"I\", 2, \"three\", \"IV\", 5, \"six\", 7, \"VIII\", 9]
');",
- "assert.notStrictEqual(mixedNumbers.toString().search(/\\.push\\(/), -1, 'message: The mixedNumbers
function should utilize the push()
method');",
- "assert.notStrictEqual(mixedNumbers.toString().search(/\\.unshift\\(/), -1, 'message: The mixedNumbers
function should utilize the unshift()
method');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d78b2367417b2b2512b0f",
- "title": "Remove Items from an Array with pop() and shift()",
- "description": [
- "Both push()
and unshift()
have corresponding methods that are nearly functional opposites: pop()
and shift()
. As you may have guessed by now, instead of adding, pop()
removes an element from the end of an array, while shift()
removes an element from the beginning. The key difference between pop()
and shift()
and their cousins push()
and unshift()
, is that neither method takes parameters, and each only allows an array to be modified by a single element at a time.",
- "Let's take a look:",
- "let greetings = ['whats up?', 'hello', 'see ya!'];
",
- "We can also return the value of the removed element with either method like this:",
- "
greetings.pop();
// now equals ['whats up?', 'hello']
greetings.shift();
// now equals ['hello']let popped = greetings.pop();
",
- "
// returns 'hello'
// greetings now equals []
",
- "We have defined a function, popShift
, which takes an array as an argument and returns a new array. Modify the function, using pop()
and shift()
, to remove the first and last elements of the argument array, and assign the removed elements to their corresponding variables, so that the returned array contains their values."
- ],
- "challengeSeed": [
- "function popShift(arr) {",
- " let popped; // change this line",
- " let shifted; // change this line",
- " return [shifted, popped];",
- "}",
- "",
- "// do not change code below this line",
- "console.log(popShift(['challenge', 'is', 'not', 'complete']));"
- ],
- "tests": [
- "assert.deepEqual(popShift(['challenge', 'is', 'not', 'complete']), [\"challenge\", \"complete\"], 'message: popShift([\"challenge\", \"is\", \"not\", \"complete\"])
should return [\"challenge\", \"complete\"]
');",
- "assert.notStrictEqual(popShift.toString().search(/\\.pop\\(/), -1, 'message: The popShift
function should utilize the pop()
method');",
- "assert.notStrictEqual(popShift.toString().search(/\\.shift\\(/), -1, 'message: The popShift
function should utilize the shift()
method');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d78b2367417b2b2512b10",
- "title": "Remove Items Using splice()",
- "description": [
- "Ok, so we've learned how to remove elements from the beginning and end of arrays using shift()
and pop()
, but what if we want to remove an element from somewhere in the middle? Or remove more than one element at once? Well, that's where splice()
comes in. splice()
allows us to do just that: remove any number of consecutive elements from anywhere in an array.",
- "splice()
can take up to 3 parameters, but for now, we'll focus on just the first 2. The first two parameters of splice()
are integers which represent indexes, or positions, of the array that splice()
is being called upon. And remember, arrays are zero-indexed, so to indicate the first element of an array, we would use 0
. splice()
's first parameter represents the index on the array from which to begin removing elements, while the second parameter indicates the number of elements to delete. For example:",
- "let array = ['today', 'was', 'not', 'so', 'great'];
",
- "
array.splice(2, 2);
// remove 2 elements beginning with the 3rd element
// array now equals ['today', 'was', 'great']splice()
not only modifies the array it's being called on, but it also returns a new array containing the value of the removed elements:",
- "let array = ['I', 'am', 'feeling', 'really', 'happy'];
",
- "
let newArray = array.splice(3, 2);
// newArray equals ['really', 'happy']
",
- "We've defined a function, sumOfTen
, which takes an array as an argument and returns the sum of that array's elements. Modify the function, using splice()
, so that it returns a value of 10
."
- ],
- "challengeSeed": [
- "function sumOfTen(arr) {",
- " // change code below this line",
- " ",
- " // change code above this line",
- " return arr.reduce((a, b) => a + b);",
- "}",
- "",
- "// do not change code below this line",
- "console.log(sumOfTen([2, 5, 1, 5, 2, 1]));"
- ],
- "tests": [
- "assert.strictEqual(sumOfTen([2, 5, 1, 5, 2, 1]), 10, 'message: sumOfTen
should return 10');",
- "assert.notStrictEqual(sumOfTen.toString().search(/\\.splice\\(/), -1, 'message: The sumOfTen
function should utilize the splice()
method');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d78b3367417b2b2512b11",
- "title": "Add Items Using splice()",
- "description": [
- "Remember in the last challenge we mentioned that splice()
can take up to three parameters? Well, we can go one step further with splice()
— in addition to removing elements, we can use that third parameter, which represents one or more elements, to add them as well. This can be incredibly useful for quickly switching out an element, or a set of elements, for another. For instance, let's say you're storing a color scheme for a set of DOM elements in an array, and want to dynamically change a color based on some action:",
- "function colorChange(arr, index, newColor) {
",
- "This function takes an array of hex values, an index at which to remove an element, and the new color to replace the removed element with. The return value is an array containing a newly modified color scheme! While this example is a bit oversimplified, we can see the value that utilizing
arr.splice(index, 1, newColor);
return arr;
}
let colorScheme = ['#878787', '#a08794', '#bb7e8c', '#c9b6be', '#d1becf'];
colorScheme = colorChange(colorScheme, 2, '#332327');
// we have removed '#bb7e8c' and added '#332327' in its place
// colorScheme now equals ['#878787', '#a08794', '#332327', '#c9b6be', '#d1becf']splice()
to its maximum potential can have.",
- "
",
- "We have defined a function, htmlColorNames
, which takes an array of HTML colors as an argument. Modify the function using splice()
to remove the first two elements of the array and add 'DarkSalmon'
and 'BlanchedAlmond'
in their respective places."
- ],
- "challengeSeed": [
- "function htmlColorNames(arr) {",
- " // change code below this line",
- " ",
- " // change code above this line",
- " return arr;",
- "} ",
- " ",
- "// do not change code below this line",
- "console.log(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurqoise', 'FireBrick']));"
- ],
- "tests": [
- "assert.deepEqual(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurqoise', 'FireBrick']), ['DarkSalmon', 'BlanchedAlmond', 'LavenderBlush', 'PaleTurqoise', 'FireBrick'], 'message: htmlColorNames
should return [\"DarkSalmon\", \"BlanchedAlmond\", \"LavenderBlush\", \"PaleTurqoise\", \"FireBrick\"]
');",
- "assert(/.splice/.test(code), 'message: The htmlColorNames
function should utilize the splice()
method');",
- "assert(!/shift|unshift/.test(code), 'message: You should not use shift()
or unshift()
.');",
- "assert(!/\\[\\d\\]\\s*=/.test(code), 'message: You should not use array bracket notation.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7a367417b2b2512b12",
- "title": "Copy Array Items Using slice()",
- "description": [
- "The next method we will cover is slice()
. slice()
, rather than modifying an array, copies, or extracts, a given number of elements to a new array, leaving the array it is called upon untouched. slice()
takes only 2 parameters — the first is the index at which to begin extraction, and the second is the index at which to stop extraction (extraction will occur up to, but not including the element at this index). Consider this:",
- "let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];
",
- "In effect, we have created a new array by extracting elements from an existing array.",
- "
let todaysWeather = weatherConditions.slice(1, 3);
// todaysWeather equals ['snow', 'sleet'];
// weatherConditions still equals ['rain', 'snow', 'sleet', 'hail', 'clear']
",
- "We have defined a function, forecast
, that takes an array as an argument. Modify the function using slice()
to extract information from the argument array and return a new array that contains the elements 'warm'
and 'sunny'
."
- ],
- "challengeSeed": [
- "function forecast(arr) {",
- " // change code below this line",
- " ",
- " return arr;",
- "}",
- "",
- "// do not change code below this line",
- "console.log(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']));"
- ],
- "tests": [
- "assert.deepEqual(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']), ['warm', 'sunny'], 'message: forecast
should return [\"warm\", \"sunny\"]');",
- "assert(/\\.slice\\(/.test(code), 'message: The
forecast
function should utilize the slice()
method');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7b367417b2b2512b13",
- "title": "Copy an Array with the Spread Operator",
- "description": [
- "While slice()
allows us to be selective about what elements of an array to copy, among several other useful tasks, ES6's new spread operator allows us to easily copy all of an array's elements, in order, with a simple and highly readable syntax. The spread syntax simply looks like this: ...
",
- "In practice, we can use the spread operator to copy an array like so:",
- "let thisArray = [true, true, undefined, false, null];
",
- "
let thatArray = [...thisArray];
// thatArray equals [true, true, undefined, false, null]
// thisArray remains unchanged, and is identical to thatArray
",
- "We have defined a function, copyMachine
which takes arr
(an array) and num
(a number) as arguments. The function is supposed to return a new array made up of num
copies of arr
. We have done most of the work for you, but it doesn't work quite right yet. Modify the function using spread syntax so that it works correctly (hint: another method we have already covered might come in handy here!)."
- ],
- "challengeSeed": [
- "function copyMachine(arr, num) {",
- " let newArr = [];",
- " while (num >= 1) {",
- " // change code below this line",
- "",
- " // change code above this line",
- " num--;",
- " }",
- " return newArr;",
- "}",
- "",
- "// change code here to test different cases:",
- "console.log(copyMachine([true, false, true], 2));"
- ],
- "tests": [
- "assert.deepEqual(copyMachine([true, false, true], 2), [[true, false, true], [true, false, true]], 'message: copyMachine([true, false, true], 2)
should return [[true, false, true], [true, false, true]]
');",
- "assert.deepEqual(copyMachine([1, 2, 3], 5), [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]], 'message: copyMachine([1, 2, 3], 5)
should return [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
');",
- "assert.deepEqual(copyMachine([true, true, null], 1), [[true, true, null]], 'message: copyMachine([true, true, null], 1)
should return [[true, true, null]]
');",
- "assert.deepEqual(copyMachine(['it works'], 3), [['it works'], ['it works'], ['it works']], 'message: copyMachine([\"it works\"], 3)
should return [[\"it works\"], [\"it works\"], [\"it works\"]]
');",
- "assert.notStrictEqual(copyMachine.toString().indexOf('.concat(_toConsumableArray(arr))'), -1, 'message: The copyMachine
function should utilize the spread operator
with array arr
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7b367417b2b2512b17",
- "title": "Combine Arrays with the Spread Operator",
- "description": [
- "Another huge advantage of the spread operator, is the ability to combine arrays, or to insert all the elements of one array into another, at any index. With more traditional syntaxes, we can concatenate arrays, but this only allows us to combine arrays at the end of one, and at the start of another. Spread syntax makes the following operation extremely simple:",
- "let thisArray = ['sage', 'rosemary', 'parsley', 'thyme'];
",
- "Using spread syntax, we have just achieved an operation that would have been more more complex and more verbose had we used traditional methods.",
- "
let thatArray = ['basil', 'cilantro', ...thisArray, 'coriander'];
// thatArray now equals ['basil', 'cilantro', 'sage', 'rosemary', 'parsley', 'thyme', 'coriander']
",
- "We have defined a function spreadOut
that returns the variable sentence
, modify the function using the spread operator so that it returns the array ['learning', 'to', 'code', 'is', 'fun']
."
- ],
- "challengeSeed": [
- "function spreadOut() {",
- " let fragment = ['to', 'code'];",
- " let sentence; // change this line",
- " return sentence;",
- "}",
- "",
- "// do not change code below this line",
- "console.log(spreadOut());"
- ],
- "tests": [
- "assert.deepEqual(spreadOut(), ['learning', 'to', 'code', 'is', 'fun'], 'message: spreadOut
should return [\"learning\", \"to\", \"code\", \"is\", \"fun\"]
');",
- "assert.notStrictEqual(spreadOut.toString().search(/[...]/), -1, 'message: The spreadOut
function should utilize spread syntax');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7b367417b2b2512b14",
- "title": "Check For The Presence of an Element With indexOf()",
- "description": [
- "Since arrays can be changed, or mutated, at any time, there's no guarantee about where a particular piece of data will be on a given array, or if that element even still exists. Luckily, JavaScript provides us with another built-in method, indexOf()
, that allows us to quickly and easily check for the presence of an element on an array. indexOf()
takes an element as a parameter, and when called, it returns the position, or index, of that element, or -1
if the element does not exist on the array.",
- "For example:",
- "let fruits = ['apples', 'pears', 'oranges', 'peaches', 'pears'];
",
- "
fruits.indexOf('dates') // returns -1
fruits.indexOf('oranges') // returns 2
fruits.indexOf('pears') // returns 1, the first index at which the element exists
",
- "indexOf()
can be incredibly useful for quickly checking for the presence of an element on an array. We have defined a function, quickCheck
, that takes an array and an element as arguments. Modify the function using indexOf()
so that it returns true
if the passed element exists on the array, and false
if it does not."
- ],
- "challengeSeed": [
- "function quickCheck(arr, elem) {",
- " // change code below this line",
- "",
- " // change code above this line",
- "}",
- "",
- "// change code here to test different cases:",
- "console.log(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'));"
- ],
- "tests": [
- "assert.strictEqual(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'), false, 'message: quickCheck([\"squash\", \"onions\", \"shallots\"], \"mushrooms\")
should return false
');",
- "assert.strictEqual(quickCheck(['squash', 'onions', 'shallots'], 'onions'), true, 'message: quickCheck([\"squash\", \"onions\", \"shallots\"], \"onions\")
should return true
');",
- "assert.strictEqual(quickCheck([3, 5, 9, 125, 45, 2], 125), true, 'message: quickCheck([3, 5, 9, 125, 45, 2], 125)
should return true
');",
- "assert.strictEqual(quickCheck([true, false, false], undefined), false, 'message: quickCheck([true, false, false], undefined)
should return false
');",
- "assert.notStrictEqual(quickCheck.toString().search(/\\.indexOf\\(/), -1, 'message: The quickCheck
function should utilize the indexOf()
method');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7b367417b2b2512b15",
- "title": "Iterate Through All an Array's Items Using For Loops",
- "description": [
- "Sometimes when working with arrays, it is very handy to be able to iterate through each item to find one or more elements that we might need, or to manipulate an array based on which data items meet a certain set of criteria. JavaScript offers several built in methods that each iterate over arrays in slightly different ways to achieve different results (such as every()
, forEach()
, map()
, etc.), however the technique which is most flexible and offers us the greatest amount of control is a simple for
loop.",
- "Consider the following:",
- "function greaterThanTen(arr) {
",
- "Using a
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] > 10) {
newArr.push(arr[i]);
}
}
return newArr;
}
greaterThanTen([2, 12, 8, 14, 80, 0, 1]);
// returns [12, 14, 80]for
loop, this function iterates through and accesses each element of the array, and subjects it to a simple test that we have created. In this way, we have easily and programmatically determined which data items are greater than 10
, and returned a new array containing those items.",
- "
",
- "We have defined a function, filteredArray
, which takes arr
, a nested array, and elem
as arguments, and returns a new array. elem
represents an element that may or may not be present on one or more of the arrays nested within arr
. Modify the function, using a for
loop, to return a filtered version of the passed array such that any array nested within arr
containing elem
has been removed."
- ],
- "challengeSeed": [
- "function filteredArray(arr, elem) {",
- " let newArr = [];",
- " // change code below this line",
- "",
- " // change code above this line",
- " return newArr;",
- "}",
- "",
- "// change code here to test different cases:",
- "console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));"
- ],
- "tests": [
- "assert.deepEqual(filteredArray([ [10, 8, 3], [14, 6, 23], [3, 18, 6] ], 18), [[10, 8, 3], [14, 6, 23]], 'message: filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18)
should return [ [10, 8, 3], [14, 6, 23] ]
');",
- "assert.deepEqual(filteredArray([ ['trumpets', 2], ['flutes', 4], ['saxophones', 2] ], 2), [['flutes', 4]], 'message: filteredArray([ [\"trumpets\", 2], [\"flutes\", 4], [\"saxophones\", 2] ], 2)
should return [ [\"flutes\", 4] ]
');",
- "assert.deepEqual(filteredArray([['amy', 'beth', 'sam'], ['dave', 'sean', 'peter']], 'peter'), [['amy', 'beth', 'sam']], 'message: filteredArray([ [\"amy\", \"beth\", \"sam\"], [\"dave\", \"sean\", \"peter\"] ], \"peter\")
should return [ [\"amy\", \"beth\", \"sam\"] ]
');",
- "assert.deepEqual(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3), [], 'message: filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3)
should return [ ]
');",
- "assert.notStrictEqual(filteredArray.toString().search(/for/), -1, 'message: The filteredArray
function should utilize a for
loop');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7b367417b2b2512b16",
- "title": "Create complex multi-dimensional arrays",
- "description": [
- "Awesome! You have just learned a ton about arrays! This has been a fairly high level overview, and there is plenty more to learn about working with arrays, much of which you will see in later sections. But before moving on to looking at Objects, lets take one more look, and see how arrays can become a bit more complex than what we have seen in previous challenges.",
- "One of the most powerful features when thinking of arrays as data structures, is that arrays can contain, or even be completely made up of other arrays. We have seen arrays that contain arrays in previous challenges, but fairly simple ones. However, arrays can contain an infinite depth of arrays that can contain other arrays, each with their own arbitrary levels of depth, and so on. In this way, an array can very quickly become very complex data structure, known as a multi-dimensional, or nested array. Consider the following example:",
- "let nestedArray = [ // top, or first level - the outer most array
",
- "While this example may seem convoluted, this level of complexity is not unheard of, or even unusual, when dealing with large amounts of data.",
- "However, we can still very easily access the deepest levels of an array this complex with bracket notation:",
- "
['deep'], // an array within an array, 2 levels of depth
[
['deeper'], ['deeper'] // 2 arrays nested 3 levels deep
],
[
[
['deepest'], ['deepest'] // 2 arrays nested 4 levels deep
],
[
[
['deepest-est?'] // an array nested 5 levels deep
]
]
]
];console.log(nestedArray[2][1][0][0][0]);
",
- "And now that we know where that piece of data is, we can reset it if we need to:",
- "
// logs: deepest-est?nestedArray[2][1][0][0][0] = 'deeper still';
",
- "
console.log(nestedArray[2][1][0][0][0]);
// now logs: deeper still
",
- "We have defined a variable, myNestedArray
, set equal to an array. Modify myNestedArray
, using any combination of strings, numbers, and booleans for data elements, so that it has exactly five levels of depth (remember, the outer-most array is level 1). Somewhere on the third level, include the string 'deep'
, on the fourth level, include the string 'deeper'
, and on the fifth level, include the string 'deepest'
."
- ],
- "challengeSeed": [
- "let myNestedArray = [",
- " // change code below this line",
- " ['unshift', false, 1, 2, 3, 'complex', 'nested'],",
- " ['loop', 'shift', 6, 7, 1000, 'method'],",
- " ['concat', false, true, 'spread', 'array'],",
- " ['mutate', 1327.98, 'splice', 'slice', 'push'],",
- " ['iterate', 1.3849, 7, '8.4876', 'arbitrary', 'depth']",
- " // change code above this line",
- "];"
- ],
- "tests": [
- "assert.strictEqual((function(arr) { let flattened = (function flatten(arr) { const flat = [].concat(...arr); return flat.some (Array.isArray) ? flatten(flat) : flat; })(arr); for (let i = 0; i < flattened.length; i++) { if ( typeof flattened[i] !== 'number' && typeof flattened[i] !== 'string' && typeof flattened[i] !== 'boolean') { return false } } return true })(myNestedArray), true, 'message: myNestedArray
should contain only numbers, booleans, and strings as data elements');",
- "assert.strictEqual((function(arr) {let depth = 0;function arrayDepth(array, i, d) { if (Array.isArray(array[i])) { arrayDepth(array[i], 0, d + 1);} else { depth = (d > depth) ? d : depth;}if (i < array.length) { arrayDepth(array, i + 1, d);} }arrayDepth(arr, 0, 0);return depth;})(myNestedArray), 4, 'message: myNestedArray
should have exactly 5 levels of depth');",
- "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep')[0] === 2, 'message: myNestedArray
should contain exactly one occurrence of the string \"deep\"
on an array nested 3 levels deep');",
- "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper')[0] === 3, 'message: myNestedArray
should contain exactly one occurrence of the string \"deeper\"
on an array nested 4 levels deep');",
- "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest')[0] === 4, 'message: myNestedArray
should contain exactly one occurrence of the string \"deepest\"
on an array nested 5 levels deep');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dac367417b2b25184d3",
- "title": "Introduction to Objects",
- "description": [
- [
- "",
- "",
- "The next data structure we will discuss is the JavaScript object. Like arrays, objects are a fundamental part of JavaScript. However, it is probably safe to say that objects surpass arrays in flexibility, usefulness and in their overall importance to the language — in fact, you may have heard this line before: 'In JavaScript, everything is an object.'
While an understanding of objects is important to understand the inner workings of JavaScript functions or JavaScript's object-oriented capabilities, JavaScript objects at a basic level are actually just key-value pair stores, a commonly used data structure across almost all programming languages. Here, we will confine our discussion to JavaScript objects in this capacity.",
- ""
- ],
- [
- "",
- "",
- "Key-value pair data structures go by different names depending on the language and the specific details of the data structure. The terms dictionary, map, and hash table all refer to the notion of a data structure in which specific keys, or properties, are mapped to specific values.
Objects, and other similar key-value pair data structures, offer some very useful benefits. One clear benefit is that they allow us to structure our data in an intuitive way; properties can be nested to an arbitrary depth, and values can be anything, including arrays and even other objects.
Largely due to this flexibility, objects are also the foundation for JavaScript Object Notation, or JSON, which is a widely used method of sending data across the web.",
- ""
- ],
- [
- "",
- "",
- "Another powerful advantage of key-value pair data structures is constant lookup time. What this means, is that when you request the value of a specific property, you will get the value back in the same amount of time (theoretically) regardless of the number of entries in the object. If you had an object with 5 entries or one that held a collection of 1,000,000, you could still retrieve property values or check if a key exists in the same amount of time.
The reason for this fast lookup time, is that internally, the object is storing properties using a hashing mechanism which allows it to know exactly where it has stored different property values. If you want to learn more about this please take a look at the optional Advanced Data Structures challenges. All you should remember for now is that performant access to flexibly structured data make key-value stores very attractive data structures useful in a wide variety of settings.",
- ""
- ],
- [
- "",
- "",
- "
In JavaScript, objects are written as comma-separated lists of key-value pairs, wrapped in curly brackets, with each key and its assigned value separated by a colon:
{ key1: 'val-1', key2: 'val-2' }
In the next few challenges, we will examine JavaScript objects more closely, and take a look at methods and techniques that allow us to access, store, and manipulate an object's data.
Note that throughout the scope of this discussion, and in general when considering JavaScript objects, the terms key and property will be used interchangeably.",
- ""
- ]
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7b7c367417b2b2512b18",
- "title": "Add Key-Value Pairs to JavaScript Objects",
- "description": [
- "At their most basic, objects are just collections of key-value pairs, or in other words, pieces of data mapped to unique identifiers that we call properties or keys. Let's take a look at a very simple example:",
- "let FCC_User = {
",
- "The above code defines an object called
username: 'awesome_coder',
followers: 572,
points: 1741,
completedProjects: 15
};FCC_User
that has four properties, each of which map to a specific value. If we wanted to know the number of followers
FCC_User
has, we can access that property by writing:",
- "let userData = FCC_User.followers;
",
- "This is called dot notation. Alternatively, we can also access the property with brackets, like so:",
- "
// userData equals 572let userData = FCC_User['followers']
",
- "Notice that with bracket notation, we enclosed
// userData equals 572followers
in quotes. This is because the brackets actually allow us to pass a variable in to be evaluated as a property name (hint: keep this in mind for later!). Had we passed followers
in without the quotes, the JavaScript engine would have attempted to evaluate it as a variable, and a ReferenceError: followers is not defined
would have been thrown.",
- "
",
- "Using the same syntax, we can also add new key-value pairs to objects. We've created a foods
object with three entries. Add three more entries: bananas
with a value of 13
, grapes
with a value of 35
, and strawberries
with a value of 27
."
- ],
- "challengeSeed": [
- "let foods = {",
- " apples: 25,",
- " oranges: 32,",
- " plums: 28",
- "};",
- "",
- "// change code below this line",
- "",
- "// change code above this line",
- "",
- "console.log(foods);"
- ],
- "tests": [
- "assert(typeof foods === 'object', 'message: foods
is an object');",
- "assert(foods.bananas === 13, 'message: The foods
object has a key \"bananas\"
with a value of 13
');",
- "assert(foods.grapes === 35, 'message: The foods
object has a key \"grapes\"
with a value of 35
');",
- "assert(foods.strawberries === 27, 'message: The foods
object has a key \"strawberries\"
with a value of 27
');",
- "assert(code.search(/bananas:/) === -1 && code.search(/grapes:/) === -1 && code.search(/strawberries:/) === -1, 'message: The key-value pairs should be set using dot or bracket notation');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7c367417b2b2512b19",
- "title": "Modify an Object Nested Within an Object",
- "description": [
- "Now let's take a look at a slightly more complex object. Object properties can be nested to an arbitrary depth, and their values can be any type of data supported by JavaScript, including arrays and even other objects. Consider the following:",
- "let nestedObject = {
",
- "
id: 28802695164,
date: 'December 31, 2016',
data: {
totalUsers: 99,
online: 80,
onlineStatus: {
active: 67,
away: 13
}
}
};nestedObject
has three unique keys: id
, whose value is a number, date
whose value is a string, and data
, whose value is an object which has yet another object nested within it. While structures can quickly become complex, we can still use the same notations to access the information we need.",
- "
",
- "Here we've defined an object, userActivity
, which includes another object nested within it. You can modify properties on this nested object in the same way you modified properties in the last challenge. Set the value of the online
key to 45
."
- ],
- "challengeSeed": [
- "let userActivity = {",
- " id: 23894201352,",
- " date: 'January 1, 2017',",
- " data: {",
- " totalUsers: 51,",
- " online: 42",
- " }",
- "};",
- "",
- "// change code below this line",
- "",
- "// change code above this line",
- "",
- "console.log(userActivity);"
- ],
- "tests": [
- "assert('id' in userActivity && 'date' in userActivity && 'data' in userActivity, 'message: userActivity
has id
, date
and data
properties');",
- "assert('totalUsers' in userActivity.data && 'online' in userActivity.data, 'message: userActivity
has a data
key set to an object with keys totalUsers
and online
');",
- "assert(userActivity.data.online === 45, 'message: The online
property nested in the data
key of userActivity
should be set to 45
');",
- "assert.strictEqual(code.search(/online: 45/), -1, 'message: The online
property is set using dot or bracket notation');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7c367417b2b2512b1a",
- "title": "Access Property Names with Bracket Notation",
- "description": [
- "In the first object challenge we mentioned the use of bracket notation as a way to access property values using the evaluation of a variable. For instance, imagine that our foods
object is being used in a program for a supermarket cash register. We have some function that sets the selectedFood
and we want to check our foods
object for the presence of that food. This might look like:",
- "let selectedFood = getCurrentFood(scannedItem);
",
- "This code will evaluate the value stored in the
let inventory = foods[selectedFood];selectedFood
variable and return the value of that key in the foods
object, or undefined
if it is not present. Bracket notation is very useful because sometimes object properties are not known before runtime or we need to access them in a more dynamic way.",
- "
",
- "We've defined a function, checkInventory
, which receives a scanned item as an argument. Return the current value of the scannedItem
key in the foods
object. You can assume that only valid keys will be provided as an argument to checkInventory
."
- ],
- "challengeSeed": [
- "let foods = {",
- " apples: 25,",
- " oranges: 32,",
- " plums: 28,",
- " bananas: 13,",
- " grapes: 35,",
- " strawberries: 27",
- "};",
- "// do not change code above this line",
- "",
- "function checkInventory(scannedItem) {",
- " // change code below this line",
- "",
- "}",
- "",
- "// change code below this line to test different cases:",
- "console.log(checkInventory(\"apples\"));"
- ],
- "tests": [
- "assert.strictEqual(typeof checkInventory, 'function', 'message: checkInventory
is a function');",
- "assert.deepEqual(foods, {apples: 25, oranges: 32, plums: 28, bananas: 13, grapes: 35, strawberries: 27}, 'message: The foods
object should have only the following key-value pairs: apples: 25
, oranges: 32
, plums: 28
, bananas: 13
, grapes: 35
, strawberries: 27
');",
- "assert.strictEqual(checkInventory('apples'), 25, 'message: checkInventory(\"apples\")
should return 25
');",
- "assert.strictEqual(checkInventory('bananas'), 13, 'message: checkInventory(\"bananas\")
should return 13
');",
- "assert.strictEqual(checkInventory('strawberries'), 27, 'message: checkInventory(\"strawberries\")
should return 27
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7c367417b2b2512b1b",
- "title": "Use the delete Keyword to Remove Object Properties",
- "description": [
- "Now you know what objects are and their basic features and advantages. In short, they are key-value stores which provide a flexible, intuitive way to structure data, and, they provide very fast lookup time. Throughout the rest of these challenges, we will describe several common operations you can perform on objects so you can become comfortable applying these useful data structures in your programs.",
- "In earlier challenges, we have both added to and modified an object's key-value pairs. Here we will see how we can remove a key-value pair from an object.",
- "Let's revisit our foods
object example one last time. If we wanted to remove the apples
key, we can remove it by using the delete
keyword like this:",
- "delete foods.apples;
",
- "
",
- "Use the delete keyword to remove the oranges
, plums
, and strawberries
keys from the foods
object."
- ],
- "challengeSeed": [
- "let foods = {",
- " apples: 25,",
- " oranges: 32,",
- " plums: 28,",
- " bananas: 13,",
- " grapes: 35,",
- " strawberries: 27",
- "};",
- "",
- "// change code below this line",
- "",
- "// change code above this line",
- "",
- "console.log(foods);"
- ],
- "tests": [
- "assert(!foods.hasOwnProperty('oranges') && !foods.hasOwnProperty('plums') && !foods.hasOwnProperty('strawberries') && Object.keys(foods).length === 3, 'message: The foods
object only has three keys: apples
, grapes
, and bananas
');",
- "assert(code.search(/oranges:/) !== -1 && code.search(/plums:/) !== -1 && code.search(/strawberries:/) !== -1, 'message: The oranges
, plums
, and strawberries
keys are removed using delete
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7d367417b2b2512b1c",
- "title": "Check if an Object has a Property",
- "description": [
- "Now we can add, modify, and remove keys from objects. But what if we just wanted to know if an object has a specific property? JavaScript provides us with two different ways to do this. One uses the hasOwnProperty()
method and the other uses the in
keyword. If we have an object users
with a property of Alan
, we could check for its presence in either of the following ways:",
- "users.hasOwnProperty('Alan');
",
- "
'Alan' in users;
// both return true
",
- "We've created an object, users
, with some users in it and a function isEveryoneHere
, which we pass the users
object to as an argument. Finish writing this function so that it returns true
only if the users
object contains all four names, Alan
, Jeff
, Sarah
, and Ryan
, as keys, and false
otherwise."
- ],
- "challengeSeed": [
- "let users = {",
- " Alan: {",
- " age: 27,",
- " online: true",
- " },",
- " Jeff: {",
- " age: 32,",
- " online: true",
- " },",
- " Sarah: {",
- " age: 48,",
- " online: true",
- " },",
- " Ryan: {",
- " age: 19,",
- " online: true",
- " }",
- "};",
- "",
- "function isEveryoneHere(obj) {",
- " // change code below this line",
- "",
- " // change code above this line",
- "}",
- "",
- "console.log(isEveryoneHere(users));"
- ],
- "tests": [
- "assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4, 'message: The users
object only contains the keys Alan
, Jeff
, Sarah
, and Ryan
');",
- "assert(isEveryoneHere(users) === true, 'message: The function isEveryoneHere
returns true
if Alan
, Jeff
, Sarah
, and Ryan
are properties on the users
object');",
- "assert((function() { delete users.Alan; delete users.Jeff; delete users.Sarah; delete users.Ryan; return isEveryoneHere(users) })() === false, 'message: The function isEveryoneHere
returns false
if Alan
, Jeff
, Sarah
, and Ryan
are not properties on the users
object');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7d367417b2b2512b1d",
- "title": " Iterate Through the Keys of an Object with a for...in Statement",
- "description": [
- "Sometimes you may need to iterate through all the keys within an object. This requires a specific syntax in JavaScript called a for...in statement. For our users
object, this could look like:",
- "for (let user in users) {
",
- "In this statement, we defined a variable
console.log(user);
};
// logs:
Alan
Jeff
Sarah
Ryanuser
, and as you can see, this variable was reset during each iteration to each of the object's keys as the statement looped through the object, resulting in each user's name being printed to the console.",
- "NOTE:
Objects do not maintain an ordering to stored keys like arrays do; thus a keys position on an object, or the relative order in which it appears, is irrelevant when referencing or accessing that key.",
- "
",
- "We've defined a function, countOnline
; use a for...in statement within this function to loop through the users in the users
object and return the number of users whose online
property is set to true
."
- ],
- "challengeSeed": [
- "let users = {",
- " Alan: {",
- " age: 27,",
- " online: false",
- " },",
- " Jeff: {",
- " age: 32,",
- " online: true",
- " },",
- " Sarah: {",
- " age: 48,",
- " online: false",
- " },",
- " Ryan: {",
- " age: 19,",
- " online: true",
- " }",
- "};",
- "",
- "function countOnline(obj) {",
- " // change code below this line",
- "",
- " // change code above this line",
- "}",
- "",
- "console.log(countOnline(users));"
- ],
- "tests": [
- "assert(users.Alan.online === false && users.Jeff.online === true && users.Sarah.online === false && users.Ryan.online === true, 'message: The users
object contains users Jeff
and Ryan
with online
set to true
and users Alan
and Sarah
with online
set to false
');",
- "assert((function() { users.Harry = {online: true}; users.Sam = {online: true}; users.Carl = {online: true}; return countOnline(users) })() === 5, 'message: The function countOnline
returns the number of users with the online
property set to true
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7d367417b2b2512b1e",
- "title": "Generate an Array of All Object Keys with Object.keys()",
- "description": [
- "We can also generate an array which contains all the keys stored in an object using the Object.keys()
method and passing in an object as the argument. This will return an array with strings representing each property in the object. Again, there will be no specific order to the entries in the array.",
- "
",
- "Finish writing the getArrayOfUsers
function so that it returns an array containing all the properties in the object it receives as an argument."
- ],
- "challengeSeed": [
- "let users = {",
- " Alan: {",
- " age: 27,",
- " online: false",
- " },",
- " Jeff: {",
- " age: 32,",
- " online: true",
- " },",
- " Sarah: {",
- " age: 48,",
- " online: false",
- " },",
- " Ryan: {",
- " age: 19,",
- " online: true",
- " }",
- "};",
- "",
- "function getArrayOfUsers(obj) {",
- " // change code below this line",
- "",
- " // change code above this line",
- "}",
- "",
- "console.log(getArrayOfUsers(users));"
- ],
- "tests": [
- "assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4, 'message: The users
object only contains the keys Alan
, Jeff
, Sarah
, and Ryan
');",
- "assert((function() { users.Sam = {}; users.Lewis = {}; let R = getArrayOfUsers(users); return (R.indexOf('Alan') !== -1 && R.indexOf('Jeff') !== -1 && R.indexOf('Sarah') !== -1 && R.indexOf('Ryan') !== -1 && R.indexOf('Sam') !== -1 && R.indexOf('Lewis') !== -1); })() === true, 'message: The getArrayOfUsers
function returns an array which contains all the keys in the users
object');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b7d367417b2b2512b1f",
- "title": "Modify an Array Stored in an Object",
- "description": [
- "Now you've seen all the basic operations for JavaScript objects. You can add, modify, and remove key-value pairs, check if keys exist, and iterate over all the keys in an object. As you continue learning JavaScript you will see even more versatile applications of objects. Additionally, the optional Advanced Data Structures lessons later in the curriculum also cover the ES6 Map and Set objects, both of which are similar to ordinary objects but provide some additional features. Now that you've learned the basics of arrays and objects, you're fully prepared to begin tackling more complex problems using JavaScript!",
- "
",
- "Take a look at the object we've provided in the code editor. The user
object contains three keys. The data
key contains five keys, one of which contains an array of friends
. From this, you can see how flexible objects are as data structures. We've started writing a function addFriend
. Finish writing it so that it takes a user
object and adds the name of the friend
argument to the array stored in user.data.friends
and returns that array."
- ],
- "challengeSeed": [
- "let user = {",
- " name: 'Kenneth',",
- " age: 28,",
- " data: {",
- " username: 'kennethCodesAllDay',",
- " joinDate: 'March 26, 2016',",
- " organization: 'freeCodeCamp',",
- " friends: [",
- " 'Sam',",
- " 'Kira',",
- " 'Tomo'",
- " ],",
- " location: {",
- " city: 'San Francisco',",
- " state: 'CA',",
- " country: 'USA'",
- " }",
- " }",
- "};",
- "",
- "function addFriend(userObj, friend) {",
- " // change code below this line ",
- "",
- " // change code above this line",
- "}",
- "",
- "console.log(addFriend(user, 'Pete'));"
- ],
- "tests": [
- "assert('name' in user && 'age' in user && 'data' in user, 'message: The user
object has name
, age
, and data
keys');",
- "assert((function() { let L1 = user.data.friends.length; addFriend(user, 'Sean'); let L2 = user.data.friends.length; return (L2 === L1 + 1); })(), 'message: The addFriend
function accepts a user
object and a friend
string as arguments and adds the friend to the array of friends
in the user
object');",
- "assert.deepEqual((function() { delete user.data.friends; user.data.friends = ['Sam', 'Kira', 'Tomo']; return addFriend(user, 'Pete') })(), ['Sam', 'Kira', 'Tomo', 'Pete'], 'message: addFriend(user, \"Pete\")
should return [\"Sam\", \"Kira\", \"Tomo\", \"Pete\"]
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "solutions": [],
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json
deleted file mode 100644
index c023da0c42..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json
+++ /dev/null
@@ -1,5841 +0,0 @@
-{
- "name": "Basic JavaScript",
- "time": "10 hours",
- "order": 1,
- "helpRoom": "HelpJavaScript",
- "challenges": [
- {
- "id": "bd6123c9c441eddfaeb4bdef",
- "title": "Introduction to JavaScript",
- "description": [
- "",
- "",
- "JavaScript is a high-level programming language that all modern web browsers support. It is also one of the core technologies of the web, along with HTML and CSS that you may have learned previously. This section will cover basic programming concepts in JavaScript, which range from variables and arithemtic to objects and loops.",
- "",
- "@@STEP@@"
- ],
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "bd7123c9c441eddfaeb4bdef",
- "title": "Comment Your JavaScript Code",
- "description": [
- "Comments are lines of code that JavaScript will intentionally ignore. Comments are a great way to leave notes to yourself and to other people who will later need to figure out what that code does.",
- "There are two ways to write comments in JavaScript:",
- "Using //
will tell JavaScript to ignore the remainder of the text on the current line:",
- "// This is an in-line comment.
",
- "You can make a multi-line comment beginning with /*
and ending with */
:",
- "/* This is a
",
- "Best Practice
multi-line comment */
As you write code, you should regularly add comments to clarify the function of parts of your code. Good commenting can help communicate the intent of your code—both for others and for your future self.",
- "
",
- "Try creating one of each type of comment."
- ],
- "challengeSeed": [
- ""
- ],
- "solutions": [
- "// Fake Comment\n/* Another Comment */"
- ],
- "tests": [
- "assert(code.match(/(\\/\\/)...../g), 'message: Create a //
style comment that contains at least five letters.');",
- "assert(code.match(/(\\/\\*)([^\\*\\/]{5,})(?=\\*\\/)/gm), 'message: Create a /* */
style comment that contains at least five letters.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Agrega comentarios a tu código JavaScript",
- "description": [
- "Los comentarios son líneas de código que el computador ignorará intencionalmente. Los comentarios son una gran forma de dejarte notas a ti mismo y a otras personas que luego tendrán que averiguar lo que hace que el código. ",
- "Vamos a echar un vistazo a las dos maneras en las que puedes agregar tus comentarios en JavaScript.",
- "El comentario de doble barra comentará el resto del texto en la línea donde se ubica:",
- "// Este es un comentario.
",
- "El comentario de barra-estrella-estrella-barra, comentará todo lo que haya entre los caracteres /*
y */
:",
- "/* Este es también un comentario */
",
- "Trata de crear uno de cada uno."
- ]
- },
- "fr": {
- "title": "Commentez votre code JavaScript",
- "description": [
- "Les commentaires sont des lignes de code que JavaScript va intentionnellement ignorer. Les commentaires sont un bon moyen de laisser des notes à votre intention ou pour d'autres personnes qui devront comprendre ce que fait votre code.",
- "Il y a deux façons d'écrire des commentaires en JavaScript.",
- "Utiliser //
indiquera à JavaScript d'ignorer le reste du texte sur cette même ligne:",
- "// Voici un commentaire sur une ligne.
",
- "Vous pouvez commenter plusieurs lignes en commençant par /*
et en finissant par */
:",
- "/*Voici un commentaire
",
- "Conseils",
- "Lorsque vous écrivez votre code, vous devriez ajouter régulièrement des commentaires pour clarifier l'objectif de certaines parties de votre code. De bons commentaires peuvent aider les autres et vous-même à mieux comprendre votre code.",
- "
sur plusieurs lignes */
",
- "Essayez de créer un commentaire de chaque type."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c443eddfaeb5bdef",
- "title": "Declare JavaScript Variables",
- "description": [
- "In computer science, data is anything that is meaningful to the computer. JavaScript provides seven different data types which are undefined
, null
, boolean
, string
, symbol
, number
, and object
.",
- "For example, computers distinguish between numbers, such as the number 12
, and strings
, such as \"12\"
, \"dog\"
, or \"123 cats\"
, which are collections of characters. Computers can perform mathematical operations on a number, but not on a string.",
- "Variables allow computers to store and manipulate data in a dynamic fashion. They do this by using a \"label\" to point to the data rather than using the data itself. Any of the seven data types may be stored in a variable.",
- "Variables
are similar to the x and y variables you use in mathematics, which means they're a simple name to represent the data we want to refer to. Computer variables
differ from mathematical variables in that they can store different values at different times.",
- "We tell JavaScript to create or declare a variable by putting the keyword var
in front of it, like so:",
- "var ourName;
",
- "creates a variable
called ourName
. In JavaScript we end statements with semicolons.",
- "Variable
names can be made up of numbers, letters, and $
or _
, but may not contain spaces or start with a number.",
- "
",
- "Use the var
keyword to create a variable called myName
.",
- "Hint
Look at the ourName
example if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var ourName;",
- "",
- "// Declare myName below this line",
- ""
- ],
- "tail": [
- "if(typeof myName !== \"undefined\"){(function(v){return v;})(myName);}"
- ],
- "solutions": [
- "var myName;"
- ],
- "tests": [
- "assert(/var\\s+myName\\s*;/.test(code), 'message: You should declare myName
with the var
keyword, ending with a semicolon');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Declara variables en JavaScript",
- "description": [
- "Cuando almacenamos datos en una estructura de datos
, la llamamos una variable
. Estas variables no son diferentes de las variables x e y que utilizas en matemáticas. ",
- "Vamos a crear nuestra primera variable y a llamarla \"myName\".",
- "Te darás cuenta que en myName
, no usamos un espacio, y que la \" N\"se escribe con mayúscula. Las variables en JavaScript se escriben con capitalización camello (camel case)
. Un ejemplo de capitalización camello: capitalizacionCamello.",
- "Ahora, utiliza la palabra clave var
para crear una variable llamada myName
. Establecele como valor tu nombre, entre comillas dobles. ",
- "Mira el ejemplo con ourName
si te quedas atascado."
- ]
- },
- "fr": {
- "title": "Déclarer des variables en JavaScript",
- "description": [
- "En informatique, une donnée comporte tout ce qui peut avoir du sens pour l'ordinateur. JavaScript dispose de sept types de données
différents qui sont undefined
, null
, boolean
, string
, symbol
, number
et object
.",
- "Par exemple, les ordinateurs font la différence entre les nombres tel que 12
et les strings
, tels que \"12\"
, \"dog\"
, ou \"123 cats\"
, qui sont des collections de caractères. Les ordinateurs peuvent faire des opérations mathématiques sur un nombre, mais pas sur une chaîne de caractères.",
- "Les variables permettent aux ordinateurs de stocker et manipuler les données de façon dynamique. Ils font cela en utilisant un label
qui réfère à la donnée plutôt que d'utiliser la donnée elle-même. Les sept types de données peuvent être stockés dans une variable.",
- "Les variables
sont similaires aux x et y que vous utilisez en mathématiques, ce qui veut dire que ce sont des noms simples qui représentent les données que l'on veut utiliser. Les variables
de l'ordinateur diffèrent de celles des mathématiques car elles peuvent stocker différentes valeurs à différents moments.",
- "On peut dire à JavaScript de créer ou déclarer
une variable en la précédant du mot-clé var
, comme ceci:",
- "var notreNom
;",
- "crée une variable
appelée notreNom
.On termine nos expressions avec un point virgule en JavaScript.",
- "Le nom d'une variable
peut être composé de nombres, lettres et $
ou _
, mais ne peut contenir d'espaces ou commencer par un nombre.",
- "
",
- "Utilisez le mot-clé var
pour créer une variable appelée monNom
",
- "Conseil
Regardez à l'exemple de notreNom
si vous vous êtes bloqué."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244a8",
- "title": "Storing Values with the Assignment Operator",
- "description": [
- "In JavaScript, you can store a value in a variable with the assignment operator.",
- "myVariable = 5;
",
- "This assigns the Number
value 5
to myVariable
.",
- "Assignment always goes from right to left. Everything to the right of the =
operator is resolved before the value is assigned to the variable to the left of the operator.",
- "myVar = 5;
",
- "This assigns
myNum = myVar;5
to myVar
and then resolves myVar
to 5
again and assigns it to myNum
.",
- "
",
- "Assign the value 7
to variable a
.",
- "Assign the contents of a
to variable b
."
- ],
- "releasedOn": "January 1, 2016",
- "head": [
- "if (typeof a != 'undefined') {",
- " a = undefined;",
- "}",
- "if (typeof b != 'undefined') {",
- " b = undefined;",
- "}"
- ],
- "challengeSeed": [
- "// Setup",
- "var a;",
- "var b = 2;",
- "",
- "// Only change code below this line",
- ""
- ],
- "tail": [
- "(function(a,b){return \"a = \" + a + \", b = \" + b;})(a,b);"
- ],
- "solutions": [
- "var a;\nvar b = 2;\na = 7;\nb = a;"
- ],
- "tests": [
- "assert(/var a;/.test(code) && /var b = 2;/.test(code), 'message: Do not change code above the line');",
- "assert(typeof a === 'number' && a === 7, 'message: a
should have a value of 7');",
- "assert(typeof b === 'number' && b === 7, 'message: b
should have a value of 7');",
- "assert(/b\\s*=\\s*a\\s*;/g.test(code), 'message: a
should be assigned to b
with =
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Almacenar valores con el operador igual",
- "description": [
- "En JavaScript, puedes almacenar un valor en una variable con la asignación o con el operador igual
(=
).",
- "miVariable = 5;
",
- "Asigna el valor númerico
de 5
a miVariable
.",
- "La asignación siempre va de derecha a izquierda. Todo a la derecha del operador =
es resuelto antes que el valor es asignado a la variable a la izquierda del operador.",
- "miVar = 5;
",
- "Asigna
miNum = miVar;5
a miVar
y entonces resuelve miVar
a 5
otra vez y asigna esta a miNum
.",
- "Instrucciones
",
- "Asigna el valor 7
a la variable a
.",
- "Asigna el contenido de a
a la variable b
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244a9",
- "title": "Initializing Variables with the Assignment Operator",
- "description": [
- "It is common to initialize a variable to an initial value in the same line as it is declared.",
- "var myVar = 0;
",
- "Creates a new variable called myVar
and assigns it an initial value of 0
.",
- "
",
- "Define a variable a
with var
and initialize it to a value of 9
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var ourVar = 19;",
- "",
- "// Only change code below this line",
- ""
- ],
- "tail": [
- "if(typeof a !== 'undefined') {(function(a){return \"a = \" + a;})(a);} else { (function() {return 'a is undefined';})(); }"
- ],
- "solutions": [
- "var a = 9;"
- ],
- "tests": [
- "assert(/var\\s+a\\s*=\\s*9\\s*/.test(code), 'message: Initialize a
to a value of 9
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Inicializar variables con el operador igual",
- "description": [
- "Es común inicializar una variable a un valor inicial en la misma línea que es declarada.",
- "var miVar = 0;
",
- "Crea una nueva variable llamada miVar
y le asigna un valor inicial de 0
.",
- "Instrucciones
",
- "Define una variable a
con var
e inicializala a un valor de 9
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244aa",
- "title": "Understanding Uninitialized Variables",
- "description": [
- "When JavaScript variables are declared, they have an initial value of undefined
. If you do a mathematical operation on an undefined
variable your result will be NaN
which means \"Not a Number\". If you concatenate a string with an undefined
variable, you will get a literal string of \"undefined\"
.",
- "
",
- "Initialize the three variables a
, b
, and c
with 5
, 10
, and \"I am a\"
respectively so that they will not be undefined
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Initialize these three variables",
- "var a;",
- "var b;",
- "var c;",
- "",
- "// Do not change code below this line",
- "",
- "a = a + 1;",
- "b = b + 5;",
- "c = c + \" String!\";",
- ""
- ],
- "tail": [
- "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = '\" + c + \"'\"; })(a,b,c);"
- ],
- "solutions": [
- "var a = 5;\nvar b = 10;\nvar c = \"I am a\";\na = a + 1;\nb = b + 5;\nc = c + \" String!\";"
- ],
- "tests": [
- "assert(typeof a === 'number' && a === 6, 'message: a
should be defined and evaluated to have the value of 6
');",
- "assert(typeof b === 'number' && b === 15, 'message: b
should be defined and evaluated to have the value of 15
');",
- "assert(!/undefined/.test(c) && c === \"I am a String!\", 'message: c
should not contain undefined
and should have a value of \"I am a String!\"');",
- "assert(/a = a \\+ 1;/.test(code) && /b = b \\+ 5;/.test(code) && /c = c \\+ \" String!\";/.test(code), 'message: Do not change code below the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Entendiendo variables sin inicializar",
- "description": [
- "Cuando las variables de JavaScript son declaradas, ellas tienen un valor inicial de undefined
. Si tu haces una operación matematica sobre una variable undefined
tu resultado sera NaN
el cual significa \"Not a Number\" es decir \"No es un número\". Si tu concatenas una cadena con una variable undefined
, vas a obtener una cadena literal de \"undefined\"
.",
- "Instrucciones
",
- "Inicializa las tres variables a
, b
, y c
con 5
, 10
, y \"I am a\"
respectivamente de manera que no sean undefined
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ab",
- "title": "Understanding Case Sensitivity in Variables",
- "description": [
- "In JavaScript all variables and function names are case sensitive. This means that capitalization matters.",
- "MYVAR
is not the same as MyVar
nor myvar
. It is possible to have multiple distinct variables with the same name but different casing. It is strongly recommended that for the sake of clarity, you do not use this language feature.",
- "Best Practice
",
- "Write variable names in JavaScript in camelCase. In camelCase, multi-word variable names have the first word in lowercase and the first letter of each subsequent word is capitalized.",
- "Examples:",
- "var someVariable;
",
- "
var anotherVariableName;
var thisVariableNameIsSoLong;
",
- "Modify the existing declarations and assignments so their names use camelCase.
Do not create any new variables."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Declarations",
- "var StUdLyCapVaR;",
- "var properCamelCase;",
- "var TitleCaseOver;",
- "",
- "// Assignments",
- "STUDLYCAPVAR = 10;",
- "PRoperCAmelCAse = \"A String\";",
- "tITLEcASEoVER = 9000;"
- ],
- "solutions": [
- "var studlyCapVar;\nvar properCamelCase;\nvar titleCaseOver;\n\nstudlyCapVar = 10;\nproperCamelCase = \"A String\";\ntitleCaseOver = 9000;"
- ],
- "tests": [
- "assert(typeof studlyCapVar !== 'undefined' && studlyCapVar === 10, 'message: studlyCapVar
is defined and has a value of 10
');",
- "assert(typeof properCamelCase !== 'undefined' && properCamelCase === \"A String\", 'message: properCamelCase
is defined and has a value of \"A String\"
');",
- "assert(typeof titleCaseOver !== 'undefined' && titleCaseOver === 9000, 'message: titleCaseOver
is defined and has a value of 9000
');",
- "assert(code.match(/studlyCapVar/g).length === 2, 'message: studlyCapVar
should use camelCase in both declaration and assignment sections.');",
- "assert(code.match(/properCamelCase/g).length === 2, 'message: properCamelCase
should use camelCase in both declaration and assignment sections.');",
- "assert(code.match(/titleCaseOver/g).length === 2, 'message: titleCaseOver
should use camelCase in both declaration and assignment sections.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Entendiendo la distinción en variables",
- "description": [
- "En JavaScript todas las variables y nombres de funciones distinguen entre mayúsculas y minúsculas. Esto significa que la capitalización importa.",
- "MIVAR
no es lo mismo que MiVar
o mivar
. Esto hace posible tener múltiples variables distintas con el mismo nombre pero de diferente manera. Es fuertemente recomendado por el bien de la claridad, que tu no uses esta característica del lenguaje.",
- "Mejor Práctica
",
- "Escribe nombres de variables en JavaScript en capitalizaciónCamello (camelCase). En capitalizaciónCamello, los nombres de variables con múltiples palabras tienen la primera palabra en minúsculas y la primera letra de cada palabra subsecuente es capitalizada.",
- "Ejemplos:",
- "var algunaVariable;
",
- "
var otraVariable;
var esteNombreDeVariableEsMuyLargo;Instrucciones
",
- "Repara las declaraciones y asignaciones de variables de manera que sus nombres usen capitalizaciónCamello."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb3bdef",
- "title": "Add Two Numbers with JavaScript",
- "description": [
- "Number
is a data type in JavaScript which represents numeric data.",
- "Now let's try to add two numbers using JavaScript.",
- "JavaScript uses the +
symbol as addition operation when placed between two numbers.",
- "Example",
- "myVar = 5 + 10; // assigned 15
",
- "
",
- "Change the 0
so that sum will equal 20
."
- ],
- "challengeSeed": [
- "var sum = 10 + 0;",
- ""
- ],
- "tail": [
- "(function(z){return 'sum = '+z;})(sum);"
- ],
- "solutions": [
- "var sum = 10 + 10;"
- ],
- "tests": [
- "assert(sum === 20, 'message: sum
should equal 20
');",
- "assert(/\\+/.test(code), 'message: Use the +
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Suma dos números con JavaScript",
- "description": [
- "Intentemos sumar dos números con JavaScript.",
- "JavaScript utiliza el símbolo +
para la adición.",
- "Cambie el 0
para que la suma seá igual a 20
."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb4bdef",
- "title": "Subtract One Number from Another with JavaScript",
- "description": [
- "We can also subtract one number from another.",
- "JavaScript uses the -
symbol for subtraction.",
- "",
- "Example",
- "myVar = 12 - 6; // assigned 6
",
- "",
- "
",
- "Change the 0
so the difference is 12
."
- ],
- "challengeSeed": [
- "var difference = 45 - 0;",
- "",
- ""
- ],
- "tail": [
- "(function(z){return 'difference = '+z;})(difference);"
- ],
- "solutions": [
- "var difference = 45 - 33;"
- ],
- "tests": [
- "assert(difference === 12, 'message: Make the variable difference
equal 12.');",
- "assert(/var\\s*difference\\s*=\\s*45\\s*-\\s*[0-9]*;(?!\\s*[a-zA-Z0-9]+)/.test(code),'message: Only subtract one number from 45.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Resta un número de otro con JavaScript",
- "description": [
- "También podemos restar un número de otro.",
- "JavaScript utiliza el símbolo -
de sustracción",
- "Cambia el 0
para que la diferencia sea 12
."
- ]
- }
- }
- },
- {
- "id": "cf1231c1c11feddfaeb5bdef",
- "title": "Multiply Two Numbers with JavaScript",
- "description": [
- "We can also multiply one number by another.",
- "JavaScript uses the *
symbol for multiplication of two numbers.",
- "",
- "Example",
- "myVar = 13 * 13; // assigned 169
",
- "",
- "
",
- "Change the 0
so that product will equal 80
."
- ],
- "challengeSeed": [
- "var product = 8 * 0;",
- "",
- ""
- ],
- "tail": [
- "(function(z){return 'product = '+z;})(product);"
- ],
- "solutions": [
- "var product = 8 * 10;"
- ],
- "tests": [
- "assert(product === 80,'message: Make the variable product
equal 80');",
- "assert(/\\*/.test(code), 'message: Use the *
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Multiplica dos números con JavaScript",
- "description": [
- "También podemos multiplicar un número por otro.",
- "JavaScript utiliza el símbolo *
de la multiplicación.",
- "Cambie el 0
para que el producto sea igual a 80
."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb6bdef",
- "title": "Divide One Number by Another with JavaScript",
- "description": [
- "We can also divide one number by another.",
- "JavaScript uses the /
symbol for division.",
- "",
- "Example",
- "myVar = 16 / 2; // assigned 8
",
- "",
- "
",
- "Change the 0
so that the quotient
is equal to 2
."
- ],
- "challengeSeed": [
- "var quotient = 66 / 0;",
- "",
- ""
- ],
- "tail": [
- "(function(z){return 'quotient = '+z;})(quotient);"
- ],
- "solutions": [
- "var quotient = 66 / 33;"
- ],
- "tests": [
- "assert(quotient === 2, 'message: Make the variable quotient
equal to 2.');",
- "assert(/\\d+\\s*\\/\\s*\\d+/.test(code), 'message: Use the /
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Divide un número por otro con JavaScript",
- "description": [
- "También podemos dividir un número por otro.",
- "JavaScript utiliza el símbolo /
para dividir.",
- "Cambia el 0
para que el cociente sea igual a 2
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ac",
- "title": "Increment a Number with JavaScript",
- "description": [
- "You can easily increment or add one to a variable with the ++
operator.",
- "i++;
",
- "is the equivalent of",
- "i = i + 1;
",
- "Note
The entire line becomes i++;
, eliminating the need for the equal sign.",
- "
",
- "Change the code to use the ++
operator on myVar
.",
- "Hint
Learn more about Arithmetic operators - Increment (++)."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myVar = 87;",
- "",
- "// Only change code below this line",
- "myVar = myVar + 1;",
- ""
- ],
- "tail": [
- "(function(z){return 'myVar = ' + z;})(myVar);"
- ],
- "solutions": [
- "var myVar = 87;\nmyVar++;"
- ],
- "tests": [
- "assert(myVar === 88, 'message: myVar
should equal 88
');",
- "assert(/var\\s*myVar\\s*=\\s*87;\\s*\\/*.*\\s*myVar\\+\\+;/.test(code), 'message: myVar = myVar + 1;
should be changed');",
- "assert(/[+]{2}\\s*myVar|myVar\\s*[+]{2}/.test(code), 'message: Use the ++
operator');",
- "assert(/var myVar = 87;/.test(code), 'message: Do not change code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Incrementa un número con JavaScript",
- "description": [
- "Tu puedes fácilmente incrementar o agregar uno a una variable con el operador ++
.",
- "i++
",
- "es el equivalente de",
- "i = i + 1;
",
- "Nota
Toda la línea equivale a i++
, sin necesidad del signo igual.",
- "Instrucciones
",
- "Cambia el código para usar el operador ++
sobre myVar
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ad",
- "title": "Decrement a Number with JavaScript",
- "description": [
- "You can easily decrement or decrease a variable by one with the --
operator.",
- "i--;
",
- "is the equivalent of",
- "i = i - 1;
",
- "Note
The entire line becomes i--;
, eliminating the need for the equal sign.",
- "
",
- "Change the code to use the --
operator on myVar
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myVar = 11;",
- "",
- "// Only change code below this line",
- "myVar = myVar - 1;",
- ""
- ],
- "tail": [
- "(function(z){return 'myVar = ' + z;})(myVar);"
- ],
- "solutions": [
- "var myVar = 11;\nmyVar--;"
- ],
- "tests": [
- "assert(myVar === 10, 'message: myVar
should equal 10
');",
- "assert(/var\\s*myVar\\s*=\\s*11;\\s*\\/*.*\\s*myVar--;/.test(code), 'message: myVar = myVar - 1;
should be changed');",
- "assert(/[-]{2}\\s*myVar|myVar\\s*[-]{2}/.test(code), 'message: Use the --
operator on myVar
');",
- "assert(/var myVar = 11;/.test(code), 'message: Do not change code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Decrementar un número con JavaScript",
- "description": [
- "Fácilmente puedes decrementar o disminuir una variable por uno con el operador --
.",
- "i--;
",
- "es el equivalente a",
- "i = i - 1;
",
- "Nota
Toda la línea equivale a i--;
, sin necesidad del signo igual.",
- "Instrucciones
",
- "Cambia el código para usar el operador --
en myVar
."
- ]
- }
- }
- },
- {
- "id": "cf1391c1c11feddfaeb4bdef",
- "title": "Create Decimal Numbers with JavaScript",
- "description": [
- "We can store decimal numbers in variables too. Decimal numbers are sometimes referred to as floating point numbers or floats.",
- "Note
Not all real numbers can accurately be represented in floating point. This can lead to rounding errors. Details Here.",
- "
",
- "Create a variable myDecimal
and give it a decimal value with a fractional part (e.g. 5.7
)."
- ],
- "challengeSeed": [
- "var ourDecimal = 5.7;",
- "",
- "// Only change code below this line",
- "",
- ""
- ],
- "tail": [
- "(function(){if(typeof myDecimal !== \"undefined\"){return myDecimal;}})();"
- ],
- "solutions": [
- "var myDecimal = 9.9;"
- ],
- "tests": [
- "assert(typeof myDecimal === \"number\", 'message: myDecimal
should be a number.');",
- "assert(myDecimal % 1 != 0, 'message: myDecimal
should have a decimal point'); "
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Crea números decimales con JavaScript",
- "description": [
- "Podemos almacenar números decimales en variables también. Los números decimales a veces son referidos como números de punto flotante o flotantes.",
- "Nota
No todos los números reales pueden ser exactamente representados en punto flotante. Esto puede conducir a errores de redondeo. Detalles aquí.",
- "Instrucciones
",
- "Crea una variable myDecimal
y dale un valor decimal con una parte fraccional (p.e. 5.7
)."
- ]
- }
- }
- },
- {
- "id": "bd7993c9c69feddfaeb7bdef",
- "title": "Multiply Two Decimals with JavaScript",
- "description": [
- "In JavaScript, you can also perform calculations with decimal numbers, just like whole numbers.",
- "Let's multiply two decimals together to get their product.",
- "
",
- "Change the 0.0
so that product will equal 5.0
."
- ],
- "challengeSeed": [
- "var product = 2.0 * 0.0;",
- "",
- ""
- ],
- "tail": [
- "(function(y){return 'product = '+y;})(product);"
- ],
- "solutions": [
- "var product = 2.0 * 2.5;"
- ],
- "tests": [
- "assert(product === 5.0, 'message: The variable product
should equal 5.0
.');",
- "assert(/\\*/.test(code), 'message: You should use the *
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Multiplicar dos decimales con JavaScript",
- "description": [
- "En JavaScript, también puedes realizar cálculos con números decimales, al igual que con números enteros.",
- "Vamos a multiplicar dos números decimales para obtener su producto.",
- "Instrucciones
",
- "Cambia el 0.0
para que el producto sea igual a 5.0
."
- ]
- }
- }
- },
- {
- "id": "bd7993c9ca9feddfaeb7bdef",
- "title": "Divide One Decimal by Another with JavaScript",
- "description": [
- "Now let's divide one decimal by another.",
- "
",
- "Change the 0.0
so that quotient
will equal to 2.2
."
- ],
- "challengeSeed": [
- "var quotient = 0.0 / 2.0; // Fix this line",
- "",
- ""
- ],
- "tail": [
- "(function(y){return 'quotient = '+y;})(quotient);"
- ],
- "solutions": [],
- "tests": [
- "assert(quotient === 2.2, 'message: The variable quotient
should equal 2.2
');",
- "assert(/4\\.40*\\s*\\/\\s*2\\.*0*/.test(code), 'message: You should use the /
operator to divide 4.4 by 2');",
- "assert(code.match(/quotient/g).length === 1, 'message: The quotient variable should only be assigned once');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Divide un número decimal por otro con JavaScript",
- "description": [
- "Ahora vamos a dividir un decimal por otro.",
- "Instrucciones
",
- "Cambia el 0.0
para que tu cociente sea igual a 2.2
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ae",
- "title": "Finding a Remainder in JavaScript",
- "description": [
- "The remainder operator %
gives the remainder of the division of two numbers.",
- "Example",
- "5 % 2 = 1 because
",
- "Usage
Math.floor(5 / 2) = 2 (Quotient)
2 * 2 = 4
5 - 4 = 1 (Remainder)
In mathematics, a number can be checked to be even or odd by checking the remainder of the division of the number by 2
.",
- "17 % 2 = 1 (17 is Odd)
",
- "Note
48 % 2 = 0 (48 is Even)
The remainder operator is sometimes incorrectly referred to as the \"modulus\" operator. It is very similar to modulus, but does not work properly with negative numbers.",
- "
",
- "Set remainder
equal to the remainder of 11
divided by 3
using the remainder (%
) operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Only change code below this line",
- "",
- "var remainder;",
- ""
- ],
- "tail": [
- "(function(y){return 'remainder = '+y;})(remainder);"
- ],
- "solutions": [
- "var remainder = 11 % 3;"
- ],
- "tests": [
- "assert(/var\\s+?remainder/.test(code), 'message: The variable remainder
should be initialized');",
- "assert(remainder === 2, 'message: The value of remainder
should be 2
');",
- "assert(/\\s+?remainder\\s*?=\\s*?.*%.*;/.test(code), 'message: You should use the %
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Encontrar un cociente en JavaScript",
- "description": [
- "El operador residuo %
da el residuo de la división de dos números.",
- "Ejemplo",
- "5 % 2 = 1 por que
",
- "Uso
Math.floor(5 / 2) = 2 (Cociente)
2 * 2 = 4
5 - 4 = 1 (Residuo)
En matemáticas, se puede comprobar si un número es par o impar revisando en residuo de la división del número por 2
.",
- "17 % 2 = 1 (17 es Impar)
",
- "Nota
48 % 2 = 0 (48 es Par)
El operador residuo es a veces incorrectamente referenciado como el operador \"módulo\". Este es muy parecido a módulo, pero no trabaja apropiadamente con números negativos.",
- "Instrucciones
",
- "Asigna remainder
igual al residuo de 11
dividido por 3
usando el operador residuo (%
)."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244af",
- "title": "Compound Assignment With Augmented Addition",
- "description": [
- "In programming, it is common to use assignments to modify the contents of a variable. Remember that everything to the right of the equals sign is evaluated first, so we can say:",
- "myVar = myVar + 5;
",
- "to add 5
to myVar
. Since this is such a common pattern, there are operators which do both a mathematical operation and assignment in one step.",
- "One such operator is the +=
operator.",
- "var myVar = 1;
",
- "
myVar += 5;
console.log(myVar); // Returns 6
",
- "Convert the assignments for a
, b
, and c
to use the +=
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var a = 3;",
- "var b = 17;",
- "var c = 12;",
- "",
- "// Only modify code below this line",
- "",
- "a = a + 12;",
- "b = 9 + b;",
- "c = c + 7;",
- ""
- ],
- "tail": [
- "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);"
- ],
- "solutions": [
- "var a = 3;\nvar b = 17;\nvar c = 12;\n\na += 12;\nb += 9;\nc += 7;"
- ],
- "tests": [
- "assert(a === 15, 'message: a
should equal 15
');",
- "assert(b === 26, 'message: b
should equal 26
');",
- "assert(c === 19, 'message: c
should equal 19
');",
- "assert(code.match(/\\+=/g).length === 3, 'message: You should use the +=
operator for each variable');",
- "assert(/var a = 3;/.test(code) && /var b = 17;/.test(code) && /var c = 12;/.test(code), 'message: Do not modify the code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Asignación con más",
- "description": [
- "En programación, es común usar asignaciones para modificar el contenido de una variable. Recuerda que todo lo de la derecha del signo igual es evaluado primero, así podemos decir que:",
- "miVar = miVar + 5;
",
- "para agregar 5
a miVar
. Dado que este es un patrón común, hay operadores que realizan tanto una operación matemática como una asignación en un paso.",
- "Uno de tales operadores es el operador +=
.",
- "miVar += 5;
añadirá 5
a miVar
.",
- "Instrucciones
",
- "Convierte las asignaciones para a
, b
y c
usando el operador +=
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b0",
- "title": "Compound Assignment With Augmented Subtraction",
- "description": [
- "Like the +=
operator, -=
subtracts a number from a variable.",
- "myVar = myVar - 5;
",
- "will subtract 5
from myVar
. This can be rewritten as: ",
- "myVar -= 5;
",
- "
",
- "Convert the assignments for a
, b
, and c
to use the -=
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var a = 11;",
- "var b = 9;",
- "var c = 3;",
- "",
- "// Only modify code below this line",
- "",
- "a = a - 6;",
- "b = b - 15;",
- "c = c - 1;",
- "",
- ""
- ],
- "tail": [
- "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);"
- ],
- "solutions": [
- "var a = 11;\nvar b = 9;\nvar c = 3;\n\na -= 6;\nb -= 15;\nc -= 1;\n\n"
- ],
- "tests": [
- "assert(a === 5, 'message: a
should equal 5
');",
- "assert(b === -6, 'message: b
should equal -6
');",
- "assert(c === 2, 'message: c
should equal 2
');",
- "assert(code.match(/-=/g).length === 3, 'message: You should use the -=
operator for each variable');",
- "assert(/var a = 11;/.test(code) && /var b = 9;/.test(code) && /var c = 3;/.test(code), 'message: Do not modify the code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Asignación con menos",
- "description": [
- "Al igual que el operador +=
, -=
substrae un número de una variable.",
- "miVar = miVar - 5;
",
- "substraerá 5
de miVar
. Esto puede ser reescrito como: ",
- "miVar -= 5;
",
- "Instrucciones
",
- "Convierte las asignaciones para a
, b
, y c
para usar el operador -=
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b1",
- "title": "Compound Assignment With Augmented Multiplication",
- "description": [
- "The *=
operator multiplies a variable by a number.",
- "myVar = myVar * 5;
",
- "will multiply myVar
by 5
. This can be rewritten as: ",
- "myVar *= 5;
",
- "
",
- "Convert the assignments for a
, b
, and c
to use the *=
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var a = 5;",
- "var b = 12;",
- "var c = 4.6;",
- "",
- "// Only modify code below this line",
- "",
- "a = a * 5;",
- "b = 3 * b;",
- "c = c * 10;",
- "",
- ""
- ],
- "tail": [
- "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);"
- ],
- "solutions": [
- "var a = 5;\nvar b = 12;\nvar c = 4.6;\n\na *= 5;\nb *= 3;\nc *= 10;"
- ],
- "tests": [
- "assert(a === 25, 'message: a
should equal 25
');",
- "assert(b === 36, 'message: b
should equal 36
');",
- "assert(c === 46, 'message: c
should equal 46
');",
- "assert(code.match(/\\*=/g).length === 3, 'message: You should use the *=
operator for each variable');",
- "assert(/var a = 5;/.test(code) && /var b = 12;/.test(code) && /var c = 4\\.6;/.test(code), 'message: Do not modify the code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Asignación con veces igual",
- "description": [
- "El operador *=
multiplica una variable por un número.",
- "miVar = miVar * 5;
",
- "multiplicará miVar
por 5
. Esto puede ser reescrito como: ",
- "miVar *= 5;
",
- "Instrucciones
",
- "Convierte las asignaciones para a
, b
y c
usando el operador *=
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b2",
- "title": "Compound Assignment With Augmented Division",
- "description": [
- "The /=
operator divides a variable by another number.",
- "myVar = myVar / 5;
",
- "Will divide myVar
by 5
. This can be rewritten as: ",
- "myVar /= 5;
",
- "
",
- "Convert the assignments for a
, b
, and c
to use the /=
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var a = 48;",
- "var b = 108;",
- "var c = 33;",
- "",
- "// Only modify code below this line",
- "",
- "a = a / 12;",
- "b = b / 4;",
- "c = c / 11;",
- ""
- ],
- "tail": [
- "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);"
- ],
- "solutions": [
- "var a = 48;\nvar b = 108;\nvar c = 33;\n\na /= 12;\nb /= 4;\nc /= 11;"
- ],
- "tests": [
- "assert(a === 4, 'message: a
should equal 4
');",
- "assert(b === 27, 'message: b
should equal 27
');",
- "assert(c === 3, 'message: c
should equal 3
');",
- "assert(code.match(/\\/=/g).length === 3, 'message: You should use the /=
operator for each variable');",
- "assert(/var a = 48;/.test(code) && /var b = 108;/.test(code) && /var c = 33;/.test(code), 'message: Do not modify the code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Asignación con división",
- "description": [
- "El operador /=
divide una variable por otro número.",
- "miVar = miVar / 5;
",
- "Dividirá miVar
por 5
. Esto puede ser reescrito como: ",
- "miVar /= 5;
",
- "Instrucciones
",
- "Convierte las asignaciones para a
, b
y c
para usar el operador /=
."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c444eddfaeb5bdef",
- "title": "Declare String Variables",
- "description": [
- "Previously we have used the code",
- "var myName = \"your name\";
",
- "\"your name\"
is called a string literal. It is a string because it is a series of zero or more characters enclosed in single or double quotes.",
- "
",
- "Create two new string
variables: myFirstName
and myLastName
and assign them the values of your first and last name, respectively."
- ],
- "challengeSeed": [
- "// Example",
- "var firstName = \"Alan\";",
- "var lastName = \"Turing\";",
- "",
- "// Only change code below this line",
- "",
- ""
- ],
- "tail": [
- "if(typeof myFirstName !== \"undefined\" && typeof myLastName !== \"undefined\"){(function(){return myFirstName + ', ' + myLastName;})();}"
- ],
- "solutions": [
- "var myFirstName = \"Alan\";\nvar myLastName = \"Turing\";"
- ],
- "tests": [
- "assert((function(){if(typeof myFirstName !== \"undefined\" && typeof myFirstName === \"string\" && myFirstName.length > 0){return true;}else{return false;}})(), 'message: myFirstName
should be a string with at least one character in it.');",
- "assert((function(){if(typeof myLastName !== \"undefined\" && typeof myLastName === \"string\" && myLastName.length > 0){return true;}else{return false;}})(), 'message: myLastName
should be a string with at least one character in it.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Declara variables tipo cadena",
- "description": [
- "En el reto anterior, se utilizó el código myName var = \"su nombre\"
. Esto es lo que llamamos una variable tipo cadena
. No es nada más que una \"cadena\" de caracteres. Las cadenas en JavaScript siempre se encierran entre comillas. ",
- "Ahora vamos a crear dos nuevas variables tipo cadena: myFirstName
y myLastName
y asignarles los valores de tu nombre y tu apellido, respectivamente."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b5",
- "title": "Escaping Literal Quotes in Strings",
- "description": [
- "When you are defining a string you must start and end with a single or double quote. What happens when you need a literal quote: \"
or '
inside of your string?",
- "In JavaScript, you can escape a quote from considering it as an end of string quote by placing a backslash (\\
) in front of the quote.",
- "var sampleStr = \"Alan said, \\\"Peter is learning JavaScript\\\".\";
",
- "This signals to JavaScript that the following quote is not the end of the string, but should instead appear inside the string. So if you were to print this to the console, you would get:",
- "Alan said, \"Peter is learning JavaScript\".
",
- "
",
- "Use backslashes to assign a string to the myStr
variable so that if you were to print it to the console, you would see:",
- "I am a \"double quoted\" string inside \"double quotes\".
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myStr = \"\"; // Change this line",
- "",
- ""
- ],
- "tail": [
- "(function(){",
- " if(typeof myStr === 'string') {",
- " console.log(\"myStr = \\\"\" + myStr + \"\\\"\");",
- " } else {",
- " console.log(\"myStr is undefined\");",
- " }",
- "})();"
- ],
- "solutions": ["var myStr = \"I am a \\\"double quoted\\\" string inside \\\"double quotes\\\".\";"],
- "tests": [
- "assert(code.match(/\\\\\"/g).length === 4 && code.match(/[^\\\\]\"/g).length === 2, 'message: You should use two double quotes ("
) and four escaped double quotes (\"
).');",
- "assert(myStr === \"I am a \\\"double quoted\\\" string inside \\\"double quotes\\\".\", 'message: Variable myStr should contain the string: I am a \"double quoted\" string inside \"double quotes\".
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Escapar comillas en cadenas de texto",
- "description": [
- "Cuando estás definiendo una cadena debes iniciar y terminar con apóstrofes o comillas. ¿Qué pasa cuando necesitas una comilla: \"
o '
dentro de tu cadena?",
- "En JavaScript, tu puedes escapar unas comillas para diferenciarlas de las comillas del final de la cadena colocando una barra invertida (\\
) antes de la cita.",
- "var cadenaEjem = \"Alan dijo, \\\"Pedro está aprendiendo JavaScript\\\".\";
",
- "Esto le indica a JavaScript que la comilla siguiente no es el fin de la cadena, sino que debe aparecer dentro de la cadena. Así que si fueras a imprimir esto en la consola, tu obtendrías:",
- "Alan dijo, \"Pedro está aprendiendo JavaScript\".
",
- "
Instructiones
",
- "Usa barras invertidaspara asigar una cadena a la variable myStr
de modo que si tu fueras a imprimirla en la consola, tu verías:",
- "I am a \"double quoted\" string inside \"double quotes\".
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b4",
- "title": "Quoting Strings with Single Quotes",
- "description": [
- "String values in JavaScript may be written with single or double quotes, as long as you start and end with the same type of quote. Unlike some other programming languages, single and double quotes work the same in JavaScript.",
- "doubleQuoteStr = \"This is a string\";
",
- "The reason why you might want to use one type of quote over the other is if you want to use both in a string. This might happen if you want to save a conversation in a string and have the conversation in quotes. Another use for it would be saving an
singleQuoteStr = 'This is also a string';<a>
tag with various attributes in quotes, all within a string.",
- "conversation = 'Finn exclaims to Jake, \"Algebraic!\"';
",
- "However, this becomes a problem if you need to use the outermost quotes within it. Remember, a string has the same kind of quote at the beginning and end. But if you have that same quote somewhere in the middle, the string will stop early and throw an error.",
- "goodStr = 'Jake asks Finn, \"Hey, let\\'s go on an adventure?\"';
",
- "In the goodStr above, you can use both quotes safely by using the backslash
badStr = 'Finn responds, \"Let's go!\"'; // Throws an error\\
as an escape character.",
- "Note
The backslash \\
should not be be confused with the forward slash /
. They do not do the same thing.",
- "
",
- "Change the provided string to a string with single quotes at the beginning and end and no escape characters.",
- "Right now, the <a>
tag in the string uses double quotes everywhere. You will need to change the outer quotes to single quotes so you can remove the escape characters."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myStr = \"Link\";",
- "",
- ""
- ],
- "tail": [
- "(function() { return \"myStr = \" + myStr; })();"
- ],
- "solutions": ["var myStr = 'Link';"],
- "tests": [
- "assert(!/\\\\/g.test(code) && myStr.match('\\\\s*\\\\s*Link\\\\s*\\\\s*'), 'message: Remove all the backslashes
(\\
)');",
- "assert(code.match(/\"/g).length === 4 && code.match(/'/g).length === 2, 'message: You should have two single quotes '
and four double quotes "
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Citando cadenas con comillas simples",
- "description": [
- "Los valores de Cadenas en JavaScript pueden ser escritos con comillas o apóstrofes, siempre y cuando inicien y terminen con el mismo tipo de cita. A diferencia de algunos lenguajes, apóstrofes y comillas son funcionalmente identicas en JavaScript.",
- "\"Esta cadena tiene \\\"comillas\\\" en esta\"
",
- "La ventaja de usar una o la otra tiene que ver con la necesidad de escapar
comillas. Si tu tienes una cadena con algunas comillas, esta puede ser difícil de leer y escribir. En su lugar, usa apóstrofes:",
- "'Esta cadena tiene \"comillas\" en esta. Y \"probablemente\" muchas de ellas.'
",
- "Instrucciones
",
- "Cambia la cadena dada de comillas a apóstrofes y quita el escape."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b6",
- "title": "Escape Sequences in Strings",
- "description": [
- "Quotes are not the only characters that can be escaped inside a string. There are two reasons to use escaping characters: First is to allow you to use characters you might not otherwise be able to type out, such as a backspace. Second is to allow you to represent multiple quotes in a string without JavaScript misinterpreting what you mean. We learned this in the previous challenge.",
- "
",
- "Note that the backslash itself must be escaped in order to display as a backslash.",
- "Code Output \\'
single quote \\\"
double quote \\\\
backslash \\n
newline \\r
carriage return \\t
tab \\b
backspace \\f
form feed
",
- "Assign the following three lines of text into the single variable myStr
using escape sequences.",
- "FirstLine
",
- "You will need to use escape sequences to insert special characters correctly. You will also need to follow the spacing as it looks above, with no spaces between escape sequences or words.",
- "Here is the text with the escape sequences written out.",
- "
\\SecondLine
ThirdLineFirstLine
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myStr; // Change this line",
- "",
- ""
- ],
- "tail": [
- "(function(){",
- "if (myStr !== undefined){",
- "console.log('myStr:\\n' + myStr);}})();"
- ],
- "solutions": [
- "var myStr = \"FirstLine\\n\\t\\\\SecondLine\\nThirdLine\";"
- ],
- "tests": [
- "assert(!/ /.test(myStr), 'message: newline
tab
backslash
SecondLinenewline
ThirdLinemyStr
should not contain any spaces');",
- "assert(/FirstLine/.test(myStr) && /SecondLine/.test(myStr) && /ThirdLine/.test(myStr), 'message: myStr
should contain the strings FirstLine
, SecondLine
and ThirdLine
(remember case sensitivity)');",
- "assert(/FirstLine\\n/.test(myStr), 'message: FirstLine
should be followed by the newline character \\n
');",
- "assert(/\\n\\t/.test(myStr), 'message: myStr
should contain a tab character \\t
which follows a newline character');",
- "assert(/\\SecondLine/.test(myStr), 'message: SecondLine
should be preceded by the backslash character \\\\
');",
- "assert(/SecondLine\\nThirdLine/.test(myStr), 'message: There should be a newline character between SecondLine
and ThirdLine
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Secuencias de escape en cadenas",
- "description": [
- "Las comillas no son el único caracter que puede ser escapado dentro de una cadena. Aquí ahí una tabla de secuencias de escape comunes:",
- "
",
- "Nota que la barra invertida por si misma tiene que ser escapada con el fin de mostrarse como una barra invertida.",
- "Código Salida \\' apostrofe \\\" comilla \\\\ barra invertida \\n nueva línea \\r retorno de carro \\t tabulación \\b retroceso \\f salto de página Instrucciones
",
- "Codifica la siguiente secuencia, separada por espacios:FirstLine
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b7",
- "title": "Concatenating Strings with Plus Operator",
- "description": [
- "In JavaScript, when the nueva línea
tabulación
barra invertida
SecondLinenueva línea
ThirdLine+
operator is used with a String
value, it is called the concatenation operator. You can build a new string out of other strings by concatenating them together.",
- "Example",
- "'My name is Alan,' + ' I concatenate.'
",
- "Note
Watch out for spaces. Concatenation does not add spaces between concatenated strings, so you'll need to add them yourself.",
- "
",
- "Build myStr
from the strings \"This is the start. \"
and \"This is the end.\"
using the +
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var ourStr = \"I come first. \" + \"I come second.\";",
- "",
- "// Only change code below this line",
- "",
- "var myStr;",
- "",
- ""
- ],
- "tail": [
- "(function(){",
- " if(typeof myStr === 'string') {",
- " return 'myStr = \"' + myStr + '\"';",
- " } else {",
- " return 'myStr is not a string';",
- " }",
- "})();"
- ],
- "solutions": [
- "var ourStr = \"I come first. \" + \"I come second.\";\nvar myStr = \"This is the start. \" + \"This is the end.\";"
- ],
- "tests": [
- "assert(myStr === \"This is the start. This is the end.\", 'message: myStr
should have a value of This is the start. This is the end.
');",
- "assert(code.match(/([\"']).*([\"'])\\s*\\+\\s*([\"']).*([\"'])/g).length > 1, 'message: Use the +
operator to build myStr
');",
- "assert(/var\\s+myStr/.test(code), 'message: myStr
should be created using the var
keyword.');",
- "assert(/myStr\\s*=/.test(code), 'message: Make sure to assign the result to the myStr
variable.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Concatenar cadenas con el operador más",
- "description": [
- "En JavaScript, cuando el operador +
es usado con un valor de Cadena
, este es llamado el operador concatenación. Tu puedes construir una nueva cadena de otras cadenas concatenandolas juntas.",
- "Ejemplo",
- "'Mi nombre es Alan,' + ' Yo concateno.'
",
- "Nota
Cuidado con los espacios. La concatenación no agrega espacios entre cadenas concatenadas, así que necesitarás agregarlos tu mismo.",
- "Instrucciones
",
- "Construye myStr
con las cadenas \"This is the start. \"
y \"This is the end.\"
usando el operador+
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b8",
- "title": "Concatenating Strings with the Plus Equals Operator",
- "description": [
- "We can also use the +=
operator to concatenate a string onto the end of an existing string variable. This can be very helpful to break a long string over several lines.",
- "Note
Watch out for spaces. Concatenation does not add spaces between concatenated strings, so you'll need to add them yourself.",
- "
",
- "Build myStr
over several lines by concatenating these two strings: \"This is the first sentence. \"
and \"This is the second sentence.\"
using the +=
operator. Use the +=
operator similar to how it is shown in the editor. Start by assigning the first string to myStr
, then add on the second string."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var ourStr = \"I come first. \";",
- "ourStr += \"I come second.\";",
- "",
- "// Only change code below this line",
- "",
- "var myStr;",
- "",
- ""
- ],
- "tail": [
- "(function(){",
- " if(typeof myStr === 'string') {",
- " return 'myStr = \"' + myStr + '\"';",
- " } else {",
- " return 'myStr is not a string';",
- " }",
- "})();"
- ],
- "solutions": [
- "var ourStr = \"I come first. \";\nourStr += \"I come second.\";\n\nvar myStr = \"This is the first sentence. \";\nmyStr += \"This is the second sentence.\";"
- ],
- "tests": [
- "assert(myStr === \"This is the first sentence. This is the second sentence.\", 'message: myStr
should have a value of This is the first sentence. This is the second sentence.
');",
- "assert(code.match(/\\w\\s*\\+=\\s*[\"']/g).length > 1 && code.match(/\\w\\s*\\=\\s*[\"']/g).length > 1, 'message: Use the +=
operator to build myStr
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Concatenar cadenas con el operador mas igual",
- "description": [
- "Nosotros también podemos usar el operador +=
para concatenar una cadena al final de una variable de cadena existente. Esto puede ser muy útil para romper una cadena larga sobre varias líneas.",
- "Nota
Cuidado con los espacios. La concatenación no agrega espacios entre cadenas concatenadas, así que necesitarás añadirlos tu mismo.",
- "Instrucciones
",
- "Construye myStr
sobre varias líneas concatenando estas dos cadenas:\"This is the first sentence. \"
y \"This is the second sentence.\"
usando el operador +=
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244b9",
- "title": "Constructing Strings with Variables",
- "description": [
- "Sometimes you will need to build a string, Mad Libs style. By using the concatenation operator (+
), you can insert one or more variables into a string you're building.",
- "
",
- "Set myName
to a string equal to your name and build myStr
with myName
between the strings \"My name is \"
and \" and I am well!\"
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var ourName = \"freeCodeCamp\";",
- "var ourStr = \"Hello, our name is \" + ourName + \", how are you?\";",
- "",
- "// Only change code below this line",
- "var myName;",
- "var myStr;",
- "",
- ""
- ],
- "tail": [
- "(function(){",
- " var output = [];",
- " if(typeof myName === 'string') {",
- " output.push('myName = \"' + myName + '\"');",
- " } else {",
- " output.push('myName is not a string');",
- " }",
- " if(typeof myStr === 'string') {",
- " output.push('myStr = \"' + myStr + '\"');",
- " } else {",
- " output.push('myStr is not a string');",
- " }",
- " return output.join('\\n');",
- "})();"
- ],
- "solutions": [
- "var myName = \"Bob\";\nvar myStr = \"My name is \" + myName + \" and I am well!\";"
- ],
- "tests": [
- "assert(typeof myName !== 'undefined' && myName.length > 2, 'message: myName
should be set to a string at least 3 characters long');",
- "assert(code.match(/[\"']\\s*\\+\\s*myName\\s*\\+\\s*[\"']/g).length > 0, 'message: Use two +
operators to build myStr
with myName
inside it');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Construir cadenas con variables",
- "description": [
- "A veces necesitarás construir una cadena, al estilo Mad Libs. Mediante el uso del operador concatenación (+
), puedes insertar una o más variables dentro de una cadena que estés construyendo.",
- "Instrucciones
",
- "Asigna myName
a una cadena igual a tu nombre y construye myStr
con myName
entre las cadenas \"My name is \"
and \" and I am well!\"
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ed",
- "title": "Appending Variables to Strings",
- "description": [
- "Just as we can build a string over multiple lines out of string literals, we can also append variables to a string using the plus equals (+=
) operator.",
- "
",
- "Set someAdjective
and append it to myStr
using the +=
operator."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var anAdjective = \"awesome!\";",
- "var ourStr = \"freeCodeCamp is \";",
- "ourStr += anAdjective;",
- "",
- "// Only change code below this line",
- "",
- "var someAdjective;",
- "var myStr = \"Learning to code is \";",
- ""
- ],
- "tail": [
- "(function(){",
- " var output = [];",
- " if(typeof someAdjective === 'string') {",
- " output.push('someAdjective = \"' + someAdjective + '\"');",
- " } else {",
- " output.push('someAdjective is not a string');",
- " }",
- " if(typeof myStr === 'string') {",
- " output.push('myStr = \"' + myStr + '\"');",
- " } else {",
- " output.push('myStr is not a string');",
- " }",
- " return output.join('\\n');",
- "})();"
- ],
- "solutions": [
- "var anAdjective = \"awesome!\";\nvar ourStr = \"freeCodeCamp is \";\nourStr += anAdjective;\n\nvar someAdjective = \"neat\";\nvar myStr = \"Learning to code is \";\nmyStr += someAdjective;"
- ],
- "tests": [
- "assert(typeof someAdjective !== 'undefined' && someAdjective.length > 2, 'message: someAdjective
should be set to a string at least 3 characters long');",
- "assert(code.match(/myStr\\s*\\+=\\s*someAdjective\\s*/).length > 0, 'message: Append someAdjective
to myStr
using the +=
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Anexando variables a cadenas",
- "description": [
- "Al igual que podemos construir una cadena en múltiples líneas a partir de cadenas literales, nosotros podemos ademas anexar variables a una cadena usando el operador más igual (+=
).",
- "Instructiones
",
- "Asigna someAdjective
y anexalo a myStr
usando el operador +=
."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/appending-variables-to-strings"
- },
- {
- "id": "bd7123c9c448eddfaeb5bdef",
- "title": "Find the Length of a String",
- "description": [
- "You can find the length of a String
value by writing .length
after the string variable or string literal.",
- "\"Alan Peter\".length; // 10
",
- "For example, if we created a variable var firstName = \"Charles\"
, we could find out how long the string \"Charles\"
is by using the firstName.length
property.",
- "
",
- "Use the .length
property to count the number of characters in the lastName
variable and assign it to lastNameLength
."
- ],
- "challengeSeed": [
- "// Example",
- "var firstNameLength = 0;",
- "var firstName = \"Ada\";",
- "",
- "firstNameLength = firstName.length;",
- "",
- "// Setup",
- "var lastNameLength = 0;",
- "var lastName = \"Lovelace\";",
- "",
- "// Only change code below this line.",
- "",
- "lastNameLength = lastName;",
- "",
- ""
- ],
- "tail": [
- "if(typeof lastNameLength !== \"undefined\"){(function(){return lastNameLength;})();}"
- ],
- "solutions": [
- "var firstNameLength = 0;\nvar firstName = \"Ada\";\nfirstNameLength = firstName.length;\n\nvar lastNameLength = 0;\nvar lastName = \"Lovelace\";\nlastNameLength = lastName.length;"
- ],
- "tests": [
- "assert((function(){if(typeof lastNameLength !== \"undefined\" && typeof lastNameLength === \"number\" && lastNameLength === 8){return true;}else{return false;}})(), 'message: lastNameLength
should be equal to eight.');",
- "assert((function(){if(code.match(/\\.length/gi) && code.match(/\\.length/gi).length >= 2 && code.match(/var lastNameLength \\= 0;/gi) && code.match(/var lastNameLength \\= 0;/gi).length >= 1){return true;}else{return false;}})(), 'message: You should be getting the length of lastName
by using .length
like this: lastName.length
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Comprueba la propiedad longitud (length) de una variable tipo cadena",
- "description": [
- "Las estructuras de datos
tienen propiedades
. Por ejemplo, las cadenas
tienen una propiedad llamada .length
que te dirá cuántos caracteres hay en la cadena.",
- "Por ejemplo, si creamos una variable var firstName=\"Charles\"
, podemos averiguar la longitud de la cadena \"Charles\" usando la propiedad firstName.length
. ",
- "Usa la propiedad .length
para contar el número de caracteres en el variable lastName
."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c549eddfaeb5bdef",
- "title": "Use Bracket Notation to Find the First Character in a String",
- "description": [
- "Bracket notation
is a way to get a character at a specific index
within a string.",
- "Most modern programming languages, like JavaScript, don't start counting at 1 like humans do. They start at 0. This is referred to as Zero-based indexing.",
- "For example, the character at index 0 in the word \"Charles\" is \"C\". So if var firstName = \"Charles\"
, you can get the value of the first letter of the string by using firstName[0]
.",
- "
",
- "Use bracket notation to find the first character in the lastName
variable and assign it to firstLetterOfLastName
.",
- "Hint
Try looking at the firstLetterOfFirstName
variable declaration if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var firstLetterOfFirstName = \"\";",
- "var firstName = \"Ada\";",
- "",
- "firstLetterOfFirstName = firstName[0];",
- "",
- "// Setup",
- "var firstLetterOfLastName = \"\";",
- "var lastName = \"Lovelace\";",
- "",
- "// Only change code below this line",
- "firstLetterOfLastName = lastName;",
- "",
- ""
- ],
- "tail": [
- "(function(v){return v;})(firstLetterOfLastName);"
- ],
- "solutions": [
- "var firstLetterOfLastName = \"\";\nvar lastName = \"Lovelace\";\n\n// Only change code below this line\nfirstLetterOfLastName = lastName[0];"
- ],
- "tests": [
- "assert(firstLetterOfLastName === 'L', 'message: The firstLetterOfLastName
variable should have the value of L
.');",
- "assert(code.match(/firstLetterOfLastName\\s*?=\\s*?lastName\\[.*?\\]/), 'message: You should use bracket notation.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usa la notación de corchetes para encontrar el primer carácter de una cadena",
- "description": [
- "La notación de corchetes
es una forma de obtener el caracter en un índice
específico de una cadena.",
- "Los computadoras no empiezan a contar desde 1 como hacen los humanos. Comienzan en 0 ",
- "Por ejemplo, el caracter en el índice 0 en la palabra \"Charles \" es \"C\". Entonces si var firstName = \"Charles\"
, puedes obtener la primera letra de la cadena usando firstName[0]
.",
- "Usa la notación de corchetes
para encontrar el primer caracter en la variable lastName
y asignarlo a firstLetterOfLastName
.",
- "Si te atascas intenta mirar la declaración de la variable firstLetterOfFirstName
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ba",
- "title": "Understand String Immutability",
- "description": [
- "In JavaScript, String
values are immutable, which means that they cannot be altered once created.",
- "For example, the following code:",
- "var myStr = \"Bob\";
",
- "cannot change the value of
myStr[0] = \"J\";myStr
to \"Job\", because the contents of myStr
cannot be altered. Note that this does not mean that myStr
cannot be changed, just that the individual characters of a string literal cannot be changed. The only way to change myStr
would be to assign it with a new string, like this:",
- "var myStr = \"Bob\";
",
- "
myStr = \"Job\";
",
- "Correct the assignment to myStr
so it contains the string value of Hello World
using the approach shown in the example above."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var myStr = \"Jello World\";",
- "",
- "// Only change code below this line",
- "",
- "myStr[0] = \"H\"; // Fix Me",
- "",
- ""
- ],
- "tail": [
- "(function(v){return \"myStr = \" + v;})(myStr);"
- ],
- "solutions": [
- "var myStr = \"Jello World\";\nmyStr = \"Hello World\";"
- ],
- "tests": [
- "assert(myStr === \"Hello World\", 'message: myStr
should have a value of Hello World
');",
- "assert(/myStr = \"Jello World\"/.test(code), 'message: Do not change the code above the line');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Comprender la inmutabilidad de cadenas",
- "description": [
- "En JavaScript, los valores de las Cadenas
son inmutables, lo cual significa que ellos no pueden ser alterados una vez creados.",
- "Por ejemplo, el siguiente código:",
- "var miCad = \"Bob\";
",
- "no puede cambiar el valor de
myCad[0] = \"J\";miCad
a \"Job\" porque el contenido de miCad
no puede ser alterado. Nota que esto no significa que miCad
no puede ser cambiado, solo que los valores individuales de una cadena literal no pueden ser cambiados. La única manera de cambiar miCad
sería asignandola a una nueva cadena, como esta:",
- "var miCad = \"Bob\";
",
- "
miCad = \"Job\";Instrucciones
",
- "Corrige la asignación de myStr
para lograr el efecto deseado."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c450eddfaeb5bdef",
- "title": "Use Bracket Notation to Find the Nth Character in a String",
- "description": [
- "You can also use bracket notation to get the character at other positions within a string.",
- "Remember that computers start counting at 0
, so the first character is actually the zeroth character.",
- "
",
- "Let's try to set thirdLetterOfLastName
to equal the third letter of the lastName
variable using bracket notation.",
- "Hint
Try looking at the secondLetterOfFirstName
variable declaration if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var firstName = \"Ada\";",
- "var secondLetterOfFirstName = firstName[1];",
- "",
- "// Setup",
- "var lastName = \"Lovelace\";",
- "",
- "// Only change code below this line.",
- "var thirdLetterOfLastName = lastName;",
- "",
- ""
- ],
- "tail": [
- "(function(v){return v;})(thirdLetterOfLastName);"
- ],
- "solutions": [
- "var lastName = \"Lovelace\";\nvar thirdLetterOfLastName = lastName[2];"
- ],
- "tests": [
- "assert(thirdLetterOfLastName === 'v', 'message: The thirdLetterOfLastName
variable should have the value of v
.');",
- "assert(code.match(/thirdLetterOfLastName\\s*?=\\s*?lastName\\[.*?\\]/), 'message: You should use bracket notation.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usar la notación de corchetes para encontrar el n-ésimo caracter en una cadena",
- "description": [
- "También puede usar notación de corchetes
para obtener el caracter en otras posiciones dentro de una cadena.",
- "Recuerda que los computadores empiezan a contar a 0, por lo que el primer caracter es en realidad el caracter cero.",
- "Instrucciones
",
- "Vamos a tratar de asignar a thirdLetterOfLastName
la tercera letra
de la variable lastName
.",
- "Pista
Si te atascas intenta mirar la declaración de la variable secondLetterOfFirstName
."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c451eddfaeb5bdef",
- "title": "Use Bracket Notation to Find the Last Character in a String",
- "description": [
- "In order to get the last letter of a string, you can subtract one from the string's length.",
- "For example, if var firstName = \"Charles\"
, you can get the value of the last letter of the string by using firstName[firstName.length - 1]
.",
- "
",
- "Use bracket notation to find the last character in the lastName
variable.",
- "Hint
Try looking at the lastLetterOfFirstName
variable declaration if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var firstName = \"Ada\";",
- "var lastLetterOfFirstName = firstName[firstName.length - 1];",
- "",
- "// Setup",
- "var lastName = \"Lovelace\";",
- "",
- "// Only change code below this line.",
- "var lastLetterOfLastName = lastName;",
- "",
- ""
- ],
- "tail": [
- "(function(v){return v;})(lastLetterOfLastName);"
- ],
- "solutions": [
- "var firstName = \"Ada\";\nvar lastLetterOfFirstName = firstName[firstName.length - 1];\n\nvar lastName = \"Lovelace\";\nvar lastLetterOfLastName = lastName[lastName.length - 1];"
- ],
- "tests": [
- "assert(lastLetterOfLastName === \"e\", 'message: lastLetterOfLastName
should be \"e\".');",
- "assert(code.match(/\\.length/g).length === 2, 'message: You have to use .length
to get the last letter.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usa notación de corchetes para encontrar el último caracter de una cadena",
- "description": [
- "Con el fin de conseguir la última letra de una cadena, puedes restar uno a la longitud de la cadena.",
- "Por ejemplo, si var firstName = \"Charles\"
, se puede obtener la última letra usando firstName[firstName.length - 1]
. ",
- "Instrucciones
",
- "Utiliza notación de corchetes
para encontrar el último caracter de la variabel lastName
.",
- "Si te atascas intenta mirando la declaración de la variable lastLetterOfFirstName
."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c452eddfaeb5bdef",
- "title": "Use Bracket Notation to Find the Nth-to-Last Character in a String",
- "description": [
- "You can use the same principle we just used to retrieve the last character in a string to retrieve the Nth-to-last character.",
- "For example, you can get the value of the third-to-last letter of the var firstName = \"Charles\"
string by using firstName[firstName.length - 3]
",
- "
",
- "Use bracket notation to find the second-to-last character in the lastName
string.",
- "Hint
Try looking at the thirdToLastLetterOfFirstName
variable declaration if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var firstName = \"Ada\";",
- "var thirdToLastLetterOfFirstName = firstName[firstName.length - 3];",
- "",
- "// Setup",
- "var lastName = \"Lovelace\";",
- "",
- "// Only change code below this line",
- "var secondToLastLetterOfLastName = lastName;",
- "",
- ""
- ],
- "tail": [
- "(function(v){return v;})(secondToLastLetterOfLastName);"
- ],
- "solutions": [
- "var firstName = \"Ada\";\nvar thirdToLastLetterOfFirstName = firstName[firstName.length - 3];\n\nvar lastName = \"Lovelace\";\nvar secondToLastLetterOfLastName = lastName[lastName.length - 2];"
- ],
- "tests": [
- "assert(secondToLastLetterOfLastName === 'c', 'message: secondToLastLetterOfLastName
should be \"c\".');",
- "assert(code.match(/\\.length/g).length === 2, 'message: You have to use .length
to get the second last letter.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usa notación de corchetes para encontrar el n-ésimo último caracter de una cadena",
- "description": [
- "Puede utilizar el mismo principio utilizamos para recuperar el último caracter de una cadena para recuperar el n-ésimo último caracter.",
- "Por ejemplo, se puede obtener el valor de la tercera última letra de la cadena var firstName = \"Charles\"
utilizando firstName[firstName.length - 3]
",
- "Instrucciones
",
- "Usa notación de corchete
para encontrar el segundo último caracter de la cadena en lastName
.",
- "Pista
Si te atascas intenta mirando la declaración de la variable thirdToLastLetterOfFirstName
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244bb",
- "title": "Word Blanks",
- "description": [
- "We will now use our knowledge of strings to build a \"Mad Libs\" style word game we're calling \"Word Blanks\". You will create an (optionally humorous) \"Fill in the Blanks\" style sentence. Here's an example of an incomplete sentence.",
- "In a \"Mad Libs\" game, you are provided sentences with some missing words, like nouns, verbs, adjectives and adverbs. You then fill in the missing pieces with words of your choice in a way that the completed sentence makes sense.",
- "Consider this sentence - \"It was really ____, and we ____ ourselves ____\". This sentence has three missing pieces- an adjective, a verb and an adverb, and we can add words of our choice to complete it. We can then assign the completed sentence to a variable as follows:",
- "var sentence = \"It was really\" + \"hot\" + \", and we\" + \"laughed\" + \"ourselves\" + \"silly.\";
",
- "
",
- "In this challenge, we provide you with a noun, a verb, an adjective and an adverb. You need to form a complete sentence using words of your choice, along with the words we provide.",
- "You will need to use the string concatenation operator +
to build a new string, using the provided variables: myNoun
, myAdjective
, myVerb
, and myAdverb
. You will then assign the formed string to the result
variable.",
- "You will also need to account for spaces in your string, so that the final sentence has spaces between all the words. The result should be a complete sentence."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function wordBlanks(myNoun, myAdjective, myVerb, myAdverb) {",
- " // Your code below this line",
- " var result = \"\";",
- "",
- " // Your code above this line",
- " return result;",
- "}",
- "",
- "// Change the words here to test your function",
- "wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\");"
- ],
- "tail": [
- "var test1 = wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\");",
- "var test2 = wordBlanks(\"cat\", \"little\", \"hit\", \"slowly\");"
- ],
- "solutions": [
- "function wordBlanks(myNoun, myAdjective, myVerb, myAdverb) {\n var result = \"\";\n\n result = \"Once there was a \" + myNoun + \" which was very \" + myAdjective + \". \";\n result += \"It \" + myVerb + \" \" + myAdverb + \" around the yard.\";\n\n return result;\n}"
- ],
- "tests": [
- "assert(typeof wordBlanks(\"\",\"\",\"\",\"\") === 'string', 'message: wordBlanks(\"\",\"\",\"\",\"\")
should return a string.');",
- "assert(/\\bdog\\b/.test(test1) && /\\bbig\\b/.test(test1) && /\\bran\\b/.test(test1) && /\\bquickly\\b/.test(test1),'message: wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\")
should contain all of the passed in words separated by non-word characters (and any additional words in your madlib).');",
- "assert(/\\bcat\\b/.test(test2) && /\\blittle\\b/.test(test2) && /\\bhit\\b/.test(test2) && /\\bslowly\\b/.test(test2),'message: wordBlanks(\"cat\", \"little\", \"hit\", \"slowly\")
should contain all of the passed in words separated by non-word characters (and any additional words in your madlib).');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Espacios en blanco de palabras",
- "description": [
- "Ahora usaremos nuestro conocimiento de cadenas para construir un juego de palabras estilo \"Mad Libs\" que llamaremos \"Espacios en Blanco de Palabras\". Vas a crear unas oraciones estilo (opcionalmente graciosa) \"Llena los espacios en blanco\".",
- "Necesitarás usar operadores de cadenas para construir una nueva cadena result
, usando las variables previstas: myNoun
, myAdjective
, myVerb
y myAdverb
.",
- "Además, necesitarás proporcionar cadenas adicionales, las cuales no cambiarán entre las palabras proporcionadas.",
- "Nosotros hemos proporcionado un marco de referencia para probar tus resultados con diferentes palabras. La prueba correrá tu función con varias palabras diferentes para asegurarse que todas las palabras proporcionadas aparezcan en la salida, así como en tus cadenas adicionales."
- ]
- }
- }
- },
- {
- "id": "bd7993c9c69feddfaeb8bdef",
- "title": "Store Multiple Values in one Variable using JavaScript Arrays",
- "description": [
- "With JavaScript array
variables, we can store several pieces of data in one place.",
- "You start an array declaration with an opening square bracket, end it with a closing square bracket, and put a comma between each entry, like this: ",
- "var sandwich = [\"peanut butter\", \"jelly\", \"bread\"]
.",
- "
",
- "Modify the new array myArray
so that it contains both a string
and a number
(in that order).",
- "Hint
Refer to the example code in the text editor if you get stuck."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [\"John\", 23];",
- "",
- "// Only change code below this line.",
- "var myArray = [];",
- ""
- ],
- "tail": [
- "(function(z){return z;})(myArray);"
- ],
- "solutions": [
- "var myArray = [\"The Answer\", 42];"
- ],
- "tests": [
- "assert(typeof myArray == 'object', 'message: myArray
should be an array
.');",
- "assert(typeof myArray[0] !== 'undefined' && typeof myArray[0] == 'string', 'message: The first item in myArray
should be a string
.');",
- "assert(typeof myArray[1] !== 'undefined' && typeof myArray[1] == 'number', 'message: The second item in myArray
should be a number
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Almacena múltiples valores en una variable utilizando vectores en JavaScript",
- "description": [
- "Con las variables tipo vector
(o en inglés array
) podemos almacenar diversos datos en un solo lugar.",
- "Empiezas la declaración de un vector con un corchete de apertura, y terminas con un corchete de cierre, y pones una coma entre cada entrada, así: var sandwich = [\"mantequilla de maní\", \"jalea\" , \"pan\"]
. ",
- "Instrucciones
",
- "Ahora vamos a crear un nuevo vector llamado myArray
que contenga una cadena
y un número
(en ese orden).",
- "Consulta el código comentado en el editor de texto si te atascas."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb7bdef",
- "title": "Nest one Array within Another Array",
- "description": [
- "You can also nest arrays within other arrays, like this: [[\"Bulls\", 23], [\"White Sox\", 45]]
. This is also called a Multi-dimensional Array.",
- "
",
- "Create a nested array called myArray
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [[\"the universe\", 42], [\"everything\", 101010]];",
- "",
- "// Only change code below this line.",
- "var myArray = [];",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var myArray = [[1,2,3]];"
- ],
- "tests": [
- "assert(Array.isArray(myArray) && myArray.some(Array.isArray), 'message: myArray
should have at least one array nested within another array.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Anida un vector dentro de otro vector",
- "description": [
- "También puedes anidar vectores dentro de otros vectores, como este: [[\"Bulls\", 23], [\"White Sox\", 45]]
.",
- "Instrucciones
",
- "Ahora vamos a crear un vector anidado llamado myArray
."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392ca",
- "title": "Access Array Data with Indexes",
- "description": [
- "We can access the data inside arrays using indexes
.",
- "Array indexes are written in the same bracket notation that strings use, except that instead of specifying a character, they are specifying an entry in the array. Like strings, arrays use zero-based indexing, so the first element in an array is element 0
.",
- "Example",
- "var array = [50,60,70];
",
- "Note
array[0]; // equals 50
var data = array[1]; // equals 60
There shouldn't be any spaces between the array name and the square brackets, like array [0]
. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.",
- "
",
- "Create a variable called myData
and set it to equal the first value of myArray
using bracket notation."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [50,60,70];",
- "var ourData = ourArray[0]; // equals 50",
- "",
- "// Setup",
- "var myArray = [50,60,70];",
- "",
- "// Only change code below this line.",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\" && typeof myData !== \"undefined\"){(function(y,z){return 'myArray = ' + JSON.stringify(y) + ', myData = ' + JSON.stringify(z);})(myArray, myData);}"
- ],
- "solutions": [
- "var myArray = [50,60,70];\nvar myData = myArray[0];"
- ],
- "tests": [
- "assert((function(){if(typeof myArray !== 'undefined' && typeof myData !== 'undefined' && myArray[0] === myData){return true;}else{return false;}})(), 'message: The variable myData
should equal the first value of myArray
.');",
- "assert((function(){if(code.match(/\\s*=\\s*myArray\\[0\\]/g)){return true;}else{return false;}})(), 'message: The data in variable myArray
should be accessed using bracket notation.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Accede a los datos de un vector mediante índices",
- "description": [
- "Podemos acceder a los datos dentro de los vectores usando índices
.",
- "Los índices del vector se escriben en la misma notación con corchetes usado con cadenas, excepto que en lugar de especificar un caracter, especifican un elemento del vector.",
- "Por ejemplo:",
- "var array = [1,2,3];
",
- "array[0]; //es igual a 1
",
- "var data = array[1];
",
- "Instrucciones
",
- "Crea una variable llamada myData code> y asignale el primer valor del vector
myArray
."
- ]
- }
- },
- "guideUrl": "https://guide.freecodecamp.org/certificates/access-array-data-with-indexes"
- },
- {
- "id": "cf1111c1c11feddfaeb8bdef",
- "title": "Modify Array Data With Indexes",
- "description": [
- "Unlike strings, the entries of arrays are mutable and can be changed freely.",
- "Example",
- "var ourArray = [50,40,30];
",
- "Note
ourArray[0] = 15; // equals [15,40,30]
There shouldn't be any spaces between the array name and the square brackets, like array [0]
. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.",
- "
",
- "Modify the data stored at index 0
of myArray
to a value of 45
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [18,64,99];",
- "ourArray[1] = 45; // ourArray now equals [18,45,99].",
- "",
- "// Setup",
- "var myArray = [18,64,99];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var myArray = [18,64,99];\nmyArray[0] = 45;"
- ],
- "tests": [
- "assert((function(){if(typeof myArray != 'undefined' && myArray[0] == 45 && myArray[1] == 64 && myArray[2] == 99){return true;}else{return false;}})(), 'message: myArray
should now be [45,64,99].');",
- "assert((function(){if(code.match(/myArray\\[0\\]\\s*=\\s*/g)){return true;}else{return false;}})(), 'message: You should be using correct index to modify the value in myArray
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Modifica datos de un vector usando índices",
- "description": [
- "También podemos modificar los datos almacenados en vectores usando índices.",
- "Por ejemplo:",
- "var ourArray = [3,2,1];
",
- "ourArray[0] = 1; // equals [1,2,1]
",
- "Instrucciones
",
- "Ahora establece el dato almacenado en el índice 0 de myArray
para que sea el valor 3."
- ]
- }
- }
- },
- {
- "id": "56592a60ddddeae28f7aa8e1",
- "title": "Access Multi-Dimensional Arrays With Indexes",
- "description": [
- "One way to think of a multi-dimensional array, is as an array of arrays. When you use brackets to access your array, the first set of brackets refers to the entries in the outer-most (the first level) array, and each additional pair of brackets refers to the next level of entries inside.",
- "Example",
- "var arr = [
",
- "Note
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12], 13, 14]
];
arr[3]; // equals [[10,11,12], 13, 14]
arr[3][0]; // equals [10,11,12]
arr[3][0][1]; // equals 11
There shouldn't be any spaces between the array name and the square brackets, like array [0][0]
and even this array [0] [0]
is not allowed. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.",
- "
",
- "Using bracket notation select an element from myArray
such that myData
is equal to 8
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var myArray = [[1,2,3], [4,5,6], [7,8,9], [[10,11,12], 13, 14]];",
- "",
- "// Only change code below this line.",
- "var myData = myArray[0][0];",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return \"myData: \" + myData + \" myArray: \" + JSON.stringify(myArray);})();}"
- ],
- "solutions": [
- "var myArray = [[1,2,3],[4,5,6], [7,8,9], [[10,11,12], 13, 14]];\nvar myData = myArray[2][1];"
- ],
- "tests": [
- "assert(myData === 8, 'message: myData
should be equal to 8
.');",
- "assert(/myArray\\[2\\]\\[1\\]/g.test(code) && !/myData\\s*=\\s*(?:.*[-+*/%]|\\d)/g.test(code), 'message: You should be using bracket notation to read the correct value from myArray
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a vectores multi-dimensionales con índices",
- "description": [
- "Una manera de pensar un vector multi-dimensional, es como un vector de vectores. Cuando usas corchetes para acceder a tu vector, el primer conjunto de brackets se refiere a las entradas en el vector más externo y cada nivel subsecuente de brackets se refiere al siguiente nivel de vectores internos.",
- "Ejemplo",
- "var vec = [
",
- "
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12], 13, 14]
];
vec[0]; // es igual [1,2,3]
vec[1][2]; // es igual 6
vec[3][0][1]; // es igual 11Instrucciones
",
- "Lee de myArray
usando la notación corchete de modo que myData sea igual a 8
"
- ]
- }
- },
- "guideUrl": "https://guide.freecodecamp.org/certificates/access-array-data-with-indexes"
- },
- {
- "id": "56bbb991ad1ed5201cd392cb",
- "title": "Manipulate Arrays With push()",
- "description": [
- "An easy way to append data to the end of an array is via the push()
function.",
- ".push()
takes one or more parameters and \"pushes\" them onto the end of the array.",
- "var arr = [1,2,3];
",
- "
arr.push(4);
// arr is now [1,2,3,4]
",
- "Push [\"dog\", 3]
onto the end of the myArray
variable."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [\"Stimpson\", \"J\", \"cat\"];",
- "ourArray.push([\"happy\", \"joy\"]); ",
- "// ourArray now equals [\"Stimpson\", \"J\", \"cat\", [\"happy\", \"joy\"]]",
- "",
- "// Setup",
- "var myArray = [[\"John\", 23], [\"cat\", 2]];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "(function(z){return 'myArray = ' + JSON.stringify(z);})(myArray);"
- ],
- "solutions": [
- "var myArray = [[\"John\", 23], [\"cat\", 2]];\nmyArray.push([\"dog\",3]);"
- ],
- "tests": [
- "assert((function(d){if(d[2] != undefined && d[0][0] == 'John' && d[0][1] === 23 && d[2][0] == 'dog' && d[2][1] === 3 && d[2].length == 2){return true;}else{return false;}})(myArray), 'message: myArray
should now equal [[\"John\", 23], [\"cat\", 2], [\"dog\", 3]]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Manipula vectores con push()",
- "description": [
- "No sólo se pueden sacar datos del final de un vector con pop()
, también puedes empujar (push()
) datos al final del vector.",
- "Instrucciones
",
- "Empuja [\"dog\", 3]
al final de la variable myArray
."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392cc",
- "title": "Manipulate Arrays With pop()",
- "description": [
- "Another way to change the data in an array is with the .pop()
function.",
- ".pop()
is used to \"pop\" a value off of the end of an array. We can store this \"popped off\" value by assigning it to a variable. In other words, .pop()
removes the last element from an array and returns that element.",
- "Any type of entry can be \"popped\" off of an array - numbers, strings, even nested arrays.",
- "
",
- "var threeArr = [1, 4, 6];
var oneDown = threeArr.pop();
console.log(oneDown); // Returns 6
console.log(threeArr); // Returns [1, 4]
",
- "Use the .pop()
function to remove the last item from myArray
, assigning the \"popped off\" value to removedFromMyArray
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [1,2,3];",
- "var removedFromOurArray = ourArray.pop(); ",
- "// removedFromOurArray now equals 3, and ourArray now equals [1,2]",
- "",
- "// Setup",
- "var myArray = [[\"John\", 23], [\"cat\", 2]];",
- "",
- "// Only change code below this line.",
- "var removedFromMyArray;",
- "",
- ""
- ],
- "tail": [
- "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removedFromMyArray = ' + JSON.stringify(z);})(myArray, removedFromMyArray);"
- ],
- "solutions": [
- "var myArray = [[\"John\", 23], [\"cat\", 2]];\nvar removedFromMyArray = myArray.pop();"
- ],
- "tests": [
- "assert((function(d){if(d[0][0] == 'John' && d[0][1] === 23 && d[1] == undefined){return true;}else{return false;}})(myArray), 'message: myArray
should only contain [[\"John\", 23]]
.');",
- "assert(/removedFromMyArray\\s*=\\s*myArray\\s*.\\s*pop\\s*(\\s*)/.test(code), 'message: Use pop()
on myArray
');",
- "assert((function(d){if(d[0] == 'cat' && d[1] === 2 && d[2] == undefined){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray
should only contain [\"cat\", 2]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Manipula vectores con pop()",
- "description": [
- "Otra forma de cambiar los datos en un vector es con la función .pop()
.",
- ".pop()
se utiliza para \"sacar\" el valor final de un vector. Podemos almacenar el valor \"sacado\" asignando pop
a una variable por ejemplo durante su declaración.",
- "Todo tipo de datos puede ser \"sacado\" de un vector --números, cadenas, incluso los vectores anidadas.",
- "Instrucciones
",
- "Usa la función .pop()
para sacar el último elemento de myArray
y asigna ese valor \"sacado\" a removedFromMyArray
."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392cd",
- "title": "Manipulate Arrays With shift()",
- "description": [
- "pop()
always removes the last element of an array. What if you want to remove the first?",
- "That's where .shift()
comes in. It works just like .pop()
, except it removes the first element instead of the last.",
- "
",
- "Use the .shift()
function to remove the first item from myArray
, assigning the \"shifted off\" value to removedFromMyArray
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];",
- "removedFromOurArray = ourArray.shift();",
- "// removedFromOurArray now equals \"Stimpson\" and ourArray now equals [\"J\", [\"cat\"]].",
- "",
- "// Setup",
- "var myArray = [[\"John\", 23], [\"dog\", 3]];",
- "",
- "// Only change code below this line.",
- "var removedFromMyArray;",
- "",
- ""
- ],
- "tail": [
- "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removedFromMyArray = ' + JSON.stringify(z);})(myArray, removedFromMyArray);"
- ],
- "solutions": [
- "var myArray = [[\"John\", 23], [\"dog\", 3]];\n\n// Only change code below this line.\nvar removedFromMyArray = myArray.shift();"
- ],
- "tests": [
- "assert((function(d){if(d[0][0] == 'dog' && d[0][1] === 3 && d[1] == undefined){return true;}else{return false;}})(myArray), 'message: myArray
should now equal [[\"dog\", 3]]
.');",
- "assert((function(d){if(d[0] == 'John' && d[1] === 23 && typeof removedFromMyArray === 'object'){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray
should contain [\"John\", 23]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Manipula vectores con shift()",
- "description": [
- "pop()
siempre elimina el último elemento de un vector. ¿Qué pasa si quieres quitar el primero?",
- "Ahí es donde entra .shift()
. Funciona igual que .pop ()
, excepto que elimina el primer elemento en lugar del pasado. ",
- "Instrucciones
",
- "Usa la función .shift()
para eliminar el primer elemento de myArray
, y el elemento que saques asignalo a removedFromMyArra
"
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392ce",
- "title": "Manipulate Arrays With unshift()",
- "description": [
- "Not only can you shift
elements off of the beginning of an array, you can also unshift
elements to the beginning of an array i.e. add elements in front of the array.",
- ".unshift()
works exactly like .push()
, but instead of adding the element at the end of the array, unshift()
adds the element at the beginning of the array.",
- "
",
- "Add [\"Paul\",35]
to the beginning of the myArray
variable using unshift()
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [\"Stimpson\", \"J\", \"cat\"];",
- "ourArray.shift(); // ourArray now equals [\"J\", \"cat\"]",
- "ourArray.unshift(\"Happy\"); ",
- "// ourArray now equals [\"Happy\", \"J\", \"cat\"]",
- "",
- "// Setup",
- "var myArray = [[\"John\", 23], [\"dog\", 3]];",
- "myArray.shift();",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "(function(y, z){return 'myArray = ' + JSON.stringify(y);})(myArray);"
- ],
- "solutions": [
- "var myArray = [[\"John\", 23], [\"dog\", 3]];\nmyArray.shift();\nmyArray.unshift([\"Paul\", 35]);"
- ],
- "tests": [
- "assert((function(d){if(typeof d[0] === \"object\" && d[0][0] == 'Paul' && d[0][1] === 35 && d[1][0] != undefined && d[1][0] == 'dog' && d[1][1] != undefined && d[1][1] == 3){return true;}else{return false;}})(myArray), 'message: myArray
should now have [[\"Paul\", 35], [\"dog\", 3]].');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Manipula vectores con unshift()",
- "description": [
- "No sólo se puedes correr
(shift) elementos del comienzo de un vector, también puedes descorrerlos
(unshift) al comienzo.",
- "unshift()
funciona exactamente igual que push()
, pero en lugar de añadir el elemento al final del vector, unshift()
añade el elemento al comienzo del vector. ",
- "Instrucciones
",
- "Añade \"Paul\"
al comienzo de la variable myArray
usando unshift()
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244bc",
- "title": "Shopping List",
- "description": [
- "Create a shopping list in the variable myList
. The list should be a multi-dimensional array containing several sub-arrays.",
- "The first element in each sub-array should contain a string with the name of the item. The second element should be a number representing the quantity i.e.",
- "[\"Chocolate Bar\", 15]
",
- "There should be at least 5 sub-arrays in the list."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myList = [];",
- "",
- ""
- ],
- "tail": [
- "var count = 0;",
- "var isArray = false;",
- "var hasString = false;",
- "var hasNumber = false;",
- "(function(list){",
- " if(Array.isArray(myList)) {",
- " isArray = true;",
- " if(myList.length > 0) {",
- " hasString = true;",
- " hasNumber = true;",
- " myList.forEach(function(elem) {",
- " if(typeof elem[0] !== 'string') {",
- " hasString = false;",
- " }",
- " if(typeof elem[1] !== 'number') {",
- " hasNumber = false;",
- " }",
- " });",
- " }",
- " count = myList.length;",
- " return JSON.stringify(myList);",
- " } else {",
- " return \"myList is not an array\";",
- " }",
- "",
- "})(myList);"
- ],
- "solutions": [
- "var myList = [\n [\"Candy\", 10],\n [\"Potatoes\", 12],\n [\"Eggs\", 12],\n [\"Catfood\", 1],\n [\"Toads\", 9]\n];"
- ],
- "tests": [
- "assert(isArray, 'message: myList
should be an array');",
- "assert(hasString, 'message: The first elements in each of your sub-arrays must all be strings');",
- "assert(hasNumber, 'message: The second elements in each of your sub-arrays must all be numbers');",
- "assert(count > 4, 'message: You must have at least 5 items in your list');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Lista de compras",
- "description": [
- "Crea una lista de compras en la variable myList
. La lista tiene que ser un vector multidimensional conteniendo varios sub-vectores.",
- "El primer elemento en cada sub-vector debe contener una cadena con el nombre del elemento. El segundo elemento debe ser un número representando la cantidad i. e.",
- "[\"Barra de Chocolate\", 15]
",
- "Tiene que haber por lo menos 5 sub-vectores en la lista."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392cf",
- "title": "Write Reusable JavaScript with Functions",
- "description": [
- "In JavaScript, we can divide up our code into reusable parts called functions.",
- "Here's an example of a function:",
- "function functionName() {
",
- "You can call or invoke this function by using its name followed by parentheses, like this:",
- "
console.log(\"Hello World\");
}functionName();
",
- "Each time the function is called it will print out the message \"Hello World\"
on the dev console. All of the code between the curly braces will be executed every time the function is called.",
- "
",
- "
"
- ],
- "head": [
- "var logOutput = \"\";",
- "var originalConsole = console",
- "function capture() {",
- " var nativeLog = console.log;",
- " console.log = function (message) {",
- " if(message && message.trim) logOutput = message.trim();",
- " if(nativeLog.apply) {",
- " nativeLog.apply(originalConsole, arguments);",
- " } else {",
- " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
- " nativeLog(nativeMsg);",
- " }",
- " };",
- "}",
- "",
- "function uncapture() {",
- " console.log = originalConsole.log;",
- "}",
- "",
- "capture();"
- ],
- "challengeSeed": [
- "// Example",
- "function ourReusableFunction() {",
- " console.log(\"Heyya, World\");",
- "}",
- "",
- "ourReusableFunction();",
- "",
- "// Only change code below this line",
- ""
- ],
- "tail": [
- "uncapture();",
- "",
- "if (typeof reusableFunction !== \"function\") { ",
- " (function() { return \"reusableFunction is not defined\"; })();",
- "} else {",
- " (function() { return logOutput || \"console.log never called\"; })();",
- "}"
- ],
- "solutions": [
- "function reusableFunction() {\n console.log(\"Hi World\");\n}\nreusableFunction();"
- ],
- "tests": [
- "assert(typeof reusableFunction === 'function', 'message: reusableFunction
which prints \"Hi World\"
to the dev console.reusableFunction
should be a function');",
- "assert(\"Hi World\" === logOutput, 'message: reusableFunction
should output \"Hi World\" to the dev console');",
- "assert(/^\\s*reusableFunction\\(\\)\\s*;/m.test(code), 'message: Call reusableFunction
after you define it');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Escribe código JavaScript reutilizable con funciones",
- "description": [
- "En JavaScript, podemos dividir nuestro código en partes reutilizables llamadas funciones.",
- "He aquí un ejemplo de una función:",
- "function nombreDeFuncion(a, b) {
",
- "& nbsp; & nbsp; return a + b;
",
- "}
",
- "Después de escribir las líneas anteriores en nuestro código, podemos pasar valores a nuestra función y el resultado que sigue a la instrucción return
será retornado.",
- "Por ejemplo, podemos pasar los números 4
y 2
al \"llamar\" la función más adelante en nuestro código, así: nombreDeFuncion(4, 2) code >. ",
- "En este ejemplo, la función devolverá el número
6
, ya que es el resultado de 4 + 2
.",
- "Crea y llama una función de nombre myFunction
que devuelva la suma de a
y b
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244bd",
- "title": "Passing Values to Functions with Arguments",
- "description": [
- "Parameters are variables that act as placeholders for the values that are to be input to a function when it is called. When a function is defined, it is typically defined along with one or more parameters. The actual values that are input (or \"passed\") into a function when it is called are known as arguments.",
- "Here is a function with two parameters, param1
and param2
:",
- "function testFun(param1, param2) {
",
- "Then we can call
console.log(param1, param2);
}testFun
:",
- "testFun(\"Hello\", \"World\");
",
- "We have passed two arguments, \"Hello\"
and \"World\"
. Inside the function, param1
will equal \"Hello\" and param2
will equal \"World\". Note that you could call testFun
again with different arguments and the parameters would take on the value of the new arguments.",
- "
",
- "
"
- ],
- "releasedOn": "January 1, 2016",
- "head": [
- "var logOutput = \"\";",
- "var originalConsole = console",
- "function capture() {",
- " var nativeLog = console.log;",
- " console.log = function (message) {",
- " if(message) logOutput = JSON.stringify(message).trim();",
- " if(nativeLog.apply) {",
- " nativeLog.apply(originalConsole, arguments);",
- " } else {",
- " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
- " nativeLog(nativeMsg);",
- " }",
- " };",
- "}",
- "",
- "function uncapture() {",
- " console.log = originalConsole.log;",
- "}",
- "",
- "capture();"
- ],
- "challengeSeed": [
- "// Example",
- "function ourFunctionWithArgs(a, b) {",
- " console.log(a - b);",
- "}",
- "ourFunctionWithArgs(10, 5); // Outputs 5",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "uncapture();",
- "",
- "if (typeof functionWithArgs !== \"function\") { ",
- " (function() { return \"functionWithArgs is not defined\"; })();",
- "} else {",
- " (function() { return logOutput || \"console.log never called\"; })();",
- "}"
- ],
- "solutions": [
- "function functionWithArgs(a, b) {\n console.log(a + b);\n}\nfunctionWithArgs(10, 5);"
- ],
- "tests": [
- "assert(typeof functionWithArgs === 'function', 'message: functionWithArgs
that accepts two arguments and outputs their sum to the dev console.functionWithArgs
should be a function');",
- "if(typeof functionWithArgs === \"function\") { capture(); functionWithArgs(1,2); uncapture(); } assert(logOutput == 3, 'message: functionWithArgs(1,2)
should output 3
');",
- "if(typeof functionWithArgs === \"function\") { capture(); functionWithArgs(7,9); uncapture(); } assert(logOutput == 16, 'message: functionWithArgs(7,9)
should output 16
');",
- "assert(/^\\s*functionWithArgs\\s*\\(\\s*\\d+\\s*,\\s*\\d+\\s*\\)\\s*;/m.test(code), 'message: Call functionWithArgs
with two numbers after you define it.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Pasando valores a funciones con argumentos",
- "description": [
- "Los parámetros son variables que actúan como marcadores de lugar para los valores que han de ser entrada para una función cuando esta es llamada. Cuando una función es definida, es típicamente definida con uno o más parámetros. Los valores actuales que son entrada (or \"pasados\") dentro de una función cuando esta es llamada son concidos como argumentos.",
- "Aquí hay una función con dos parámetros, param1
y param2
:",
- "function testFun(param1, param2) {
",
- "Entonces nosotros podemos llamar
console.log(param1, param2);
}testFun
:",
- "testFun(\"Hello\", \"World\");
",
- "Nosotros hemos pasado dos argumentos, \"Hello\"
y \"World\"
. Dentro de la función, param1
será igual a \"Hello\" y param2
será igual a \"World\". Nota que puedes llamar testFun
otra vez con argumentos diferentes y los parámetros asumirían el valor de los nuevos argumentos.",
- "Instrucciones
",
- "
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244be",
- "title": "Global Scope and Functions",
- "description": [
- "In JavaScript, scope refers to the visibility of variables. Variables which are defined outside of a function block have Global scope. This means, they can be seen everywhere in your JavaScript code.",
- "Variables which are used without the functionWithArgs
que acepte dos argumentos y da salida a su suma en la consola.var
keyword are automatically created in the global
scope. This can create unintended consequences elsewhere in your code or when running a function again. You should always declare your variables with var
.",
- "
",
- "Using var
, declare a global
variable myGlobal
outside of any function. Initialize it with a value of 10
.",
- "Inside function fun1
, assign 5
to oopsGlobal
without using the var
keyword."
- ],
- "releasedOn": "January 1, 2016",
- "head": [
- "var logOutput = \"\";",
- "var originalConsole = console",
- "function capture() {",
- " var nativeLog = console.log;",
- " console.log = function (message) {",
- " logOutput = message;",
- " if(nativeLog.apply) {",
- " nativeLog.apply(originalConsole, arguments);",
- " } else {",
- " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
- " nativeLog(nativeMsg);",
- " }",
- " };",
- "}",
- "",
- "function uncapture() {",
- " console.log = originalConsole.log;",
- "}",
- "var oopsGlobal;",
- "capture();"
- ],
- "challengeSeed": [
- "// Declare your variable here",
- "",
- "",
- "function fun1() {",
- " // Assign 5 to oopsGlobal Here",
- " ",
- "}",
- "",
- "// Only change code above this line",
- "function fun2() {",
- " var output = \"\";",
- " if (typeof myGlobal != \"undefined\") {",
- " output += \"myGlobal: \" + myGlobal;",
- " }",
- " if (typeof oopsGlobal != \"undefined\") {",
- " output += \" oopsGlobal: \" + oopsGlobal;",
- " }",
- " console.log(output);",
- "}"
- ],
- "tail": [
- "fun1();",
- "fun2();",
- "uncapture();",
- "(function() { return logOutput || \"console.log never called\"; })();"
- ],
- "solutions": [
- "// Declare your variable here\nvar myGlobal = 10;\n\nfunction fun1() {\n // Assign 5 to oopsGlobal Here\n oopsGlobal = 5;\n}\n\n// Only change code above this line\nfunction fun2() {\n var output = \"\";\n if(typeof myGlobal != \"undefined\") {\n output += \"myGlobal: \" + myGlobal;\n }\n if(typeof oopsGlobal != \"undefined\") {\n output += \" oopsGlobal: \" + oopsGlobal;\n }\n console.log(output);\n}"
- ],
- "tests": [
- "assert(typeof myGlobal != \"undefined\", 'message: myGlobal
should be defined');",
- "assert(myGlobal === 10, 'message: myGlobal
should have a value of 10
');",
- "assert(/var\\s+myGlobal/.test(code), 'message: myGlobal
should be declared using the var
keyword');",
- "assert(typeof oopsGlobal != \"undefined\" && oopsGlobal === 5, 'message: oopsGlobal
should be a global variable and have a value of 5
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Alcance global y funciones",
- "description": [
- "En JavaScript, alcance se referiere a la visibilidad de variables. Las variables que definas fuera de un bloque de una función tienen alcance Global. Esto significa que ellas pueden ser vistas en todas partes en tu código JavaScript.",
- "Las variables que pueden ser usadas sin la palabra clave var
son automáticamente creadas en el alcance global
. Esto puede tener consecuencias no deseadas en otras partes de tu código o cuando se ejecuta una función de nuevo. Tu siempre deberías declarar tus variables con var
.",
- "Instrucciones
",
- "Declara a variable global
myGlobal
fuera de cualquier función. Inicializala para tener un valor de 10
",
- "Dentro de la función fun1
, asigna 5
a oopsGlobal
sin usar la palabra clave var
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244bf",
- "title": "Local Scope and Functions",
- "description": [
- "Variables which are declared within a function, as well as the function parameters have local scope. That means, they are only visible within that function.",
- "Here is a function myTest
with a local variable called loc
.",
- "function myTest() {
",
- "
var loc = \"foo\";
console.log(loc);
}
myTest(); // logs \"foo\"
console.log(loc); // loc is not definedloc
is not defined outside of the function.",
- "
",
- "Declare a local variable myVar
inside myLocalScope
. Run the tests and then follow the instructions commented out in the editor.",
- "Hint
Refreshing the page may help if you get stuck."
- ],
- "releasedOn": "January 1, 2016",
- "head": [
- "var logOutput = \"\";",
- "var originalConsole = console",
- "function capture() {",
- " var nativeLog = console.log;",
- " console.log = function (message) {",
- " logOutput = message;",
- " if(nativeLog.apply) {",
- " nativeLog.apply(originalConsole, arguments);",
- " } else {",
- " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
- " nativeLog(nativeMsg);",
- " }",
- " };",
- "}",
- "",
- "function uncapture() {",
- " console.log = originalConsole.log;",
- "}",
- ""
- ],
- "challengeSeed": [
- "function myLocalScope() {",
- " 'use strict'; // you shouldn't need to edit this line",
- " ",
- " console.log(myVar);",
- "}",
- "myLocalScope();",
- "",
- "// Run and check the console",
- "// myVar is not defined outside of myLocalScope",
- "console.log(myVar);",
- "",
- "// Now remove the console log line to pass the test",
- ""
- ],
- "tail": [
- "typeof myLocalScope === 'function' && (capture(), myLocalScope(), uncapture());",
- "(function() { return logOutput || \"console.log never called\"; })();"
- ],
- "solutions": [
- "function myLocalScope() {\n 'use strict';\n \n var myVar;\n console.log(myVar);\n}\nmyLocalScope();"
- ],
- "tests": [
- "assert(typeof myVar === 'undefined', 'message: No global myVar
variable');",
- "assert(/var\\s+myVar/.test(code), 'message: Add a local myVar
variable');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Alcance local y funciones",
- "description": [
- "Las variables que son declaradas dentro de una función, así como los parámetros de la función tienen alcance local. Eso significa que solo son visibles dentro de esa función.",
- "Aquí está una función myTest
con una variable local llamada loc
.",
- "function myTest() {
",
- "
var loc = \"foo\";
console.log(loc);
}
myTest(); // \"foo\"
console.log(loc); // \"undefined\"loc
no está definida fuera de la función.",
- "Instrucciones
",
- "Declara una variable local myVar
dentro de myLocalScope
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244c0",
- "title": "Global vs. Local Scope in Functions",
- "description": [
- "It is possible to have both local and global variables with the same name. When you do this, the local
variable takes precedence over the global
variable.",
- "In this example:",
- "var someVar = \"Hat\";
",
- "The function
function myFun() {
var someVar = \"Head\";
return someVar;
}myFun
will return \"Head\"
because the local
version of the variable is present.",
- "
",
- "Add a local variable to myOutfit
function to override the value of outerWear
with \"sweater\"
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var outerWear = \"T-Shirt\";",
- "",
- "function myOutfit() {",
- " // Only change code below this line",
- " ",
- " ",
- " ",
- " // Only change code above this line",
- " return outerWear;",
- "}",
- "",
- "myOutfit();"
- ],
- "solutions": [
- "var outerWear = \"T-Shirt\";\nfunction myOutfit() {\n var outerWear = \"sweater\";\n return outerWear;\n}"
- ],
- "tests": [
- "assert(outerWear === \"T-Shirt\", 'message: Do not change the value of the global outerWear
');",
- "assert(myOutfit() === \"sweater\", 'message: myOutfit
should return \"sweater\"
');",
- "assert(/return outerWear/.test(code), 'message: Do not change the return statement');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Alcance global vs. local en funciones",
- "description": [
- "Es posible tener variables locales y globales con el mismo nombre. Cuando tu haces esto, la variable local
toma precedencia sobre la variable global
.",
- "En este ejemplo:",
- "var algunaVar = \"Sombrero\";
",
- "La función
function miFun() {
var algunaVar = \"Cabeza\";
return algunaVar;
}miFun
regresará \"Cabeza\"
porque la versión local
de la variable tiene precedencia.",
- "Instrucciones
",
- "Agrega una variable local a myOutfit
para sobreescribir el valor de outerWear
con \"sweater\"
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244c2",
- "title": "Return a Value from a Function with Return",
- "description": [
- "We can pass values into a function with arguments. You can use a return
statement to send a value back out of a function.",
- "Example",
- "function plusThree(num) {
",
- "
return num + 3;
}
var answer = plusThree(5); // 8plusThree
takes an argument for num
and returns a value equal to num + 3
.",
- "
",
- "Create a function timesFive
that accepts one argument, multiplies it by 5
, and returns the new value. See the last line in the editor for an example of how you can test your timesFive
function."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "function minusSeven(num) {",
- " return num - 7;",
- "}",
- "",
- "// Only change code below this line",
- "",
- "",
- "",
- "console.log(minusSeven(10));"
- ],
- "tail": [],
- "solutions": [
- "function timesFive(num) {\n return num * 5;\n}\ntimesFive(10);"
- ],
- "tests": [
- "assert(typeof timesFive === 'function', 'message: timesFive
should be a function');",
- "assert(code.match(/timesFive\\(\\s*\\d+\\s*\\)/g), 'message: function timesFive
should be called with a number');",
- "assert(timesFive(5) === 25, 'message: timesFive(5)
should return 25
');",
- "assert(timesFive(2) === 10, 'message: timesFive(2)
should return 10
');",
- "assert(timesFive(0) === 0, 'message: timesFive(0)
should return 0
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Retorna un valor desde una función con return",
- "description": [
- "Podemos pasar valores a una función mediante los argumentos. Puedes usar una sentencia return
para enviar un valor de vuelta de una función.",
- "Ejemplo",
- "function masTres(num) {
",
- "
return num + 3;
}
var respuesta = masTres(5); // 8masTres
toma un argumento que es num
y retorna un valor igual a num + 3
.",
- "Instrucciones
",
- "Crea una función timesFive
que acepte un argumento, lo multiplique por 5
y retorne el nuevo valor."
- ]
- }
- }
- },
- {
- "id": "598e8944f009e646fc236146",
- "title": "Understanding Undefined Value returned from a Function",
- "description": [
- "A function can include the return
statement but it does not have to. In the case that the function doesn't have a return
statement, when you call it, the function processes the inner code but the returned value is undefined
.",
- "Example",
- "var sum = 0;
",
- "
function addSum(num) {
sum = sum + num;
}
var returnedValue = addSum(3); // sum will be modified but returned value is undefinedaddSum
is a function without a return
statement. The function will change the global sum
variable but the returned value of the function is undefined
",
- "
",
- "Create a function addFive
without any arguments. This function adds 5 to the sum
variable, but its returned value is undefined
."
- ],
- "releasedOn": "August 11, 2017",
- "challengeSeed": [
- "// Example",
- "var sum = 0;",
- "function addThree() {",
- " sum = sum + 3;",
- "}",
- "",
- "// Only change code below this line",
- "",
- "",
- "",
- "// Only change code above this line",
- "var returnedValue = addFive();"
- ],
- "tail": [
- "var sum = 0;",
- "function addThree() {sum = sum + 3;}",
- "addThree();",
- "addFive();"
- ],
- "solutions": [
- "function addFive() {\n sum = sum + 5;\n}"
- ],
- "tests": [
- "assert(typeof addFive === 'function', 'message: addFive
should be a function');",
- "assert(sum === 8, 'message: sum
should be equal to 8');",
- "assert(addFive() === undefined, 'message: Returned value from addFive
should be undefined
');",
- "assert(code.match(/(sum\\s*\\=\\s*sum\\s*\\+\\s*5)|(sum\\s*\\+\\=\\s*5)/g).length === 1, 'message: Inside of your functions, add 5 to the sum
variable');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "56533eb9ac21ba0edf2244c3",
- "title": "Assignment with a Returned Value",
- "description": [
- "If you'll recall from our discussion of Storing Values with the Assignment Operator, everything to the right of the equal sign is resolved before the value is assigned. This means we can take the return value of a function and assign it to a variable.",
- "Assume we have pre-defined a function sum
which adds two numbers together, then: ",
- "ourSum = sum(5, 12);
",
- "will call sum
function, which returns a value of 17
and assigns it to ourSum
variable.",
- "
",
- "Call the processArg
function with an argument of 7
and assign its return value to the variable processed
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var changed = 0;",
- "",
- "function change(num) {",
- " return (num + 5) / 3;",
- "}",
- "",
- "changed = change(10);",
- "",
- "// Setup",
- "var processed = 0;",
- "",
- "function processArg(num) {",
- " return (num + 3) / 5;",
- "}",
- "",
- "// Only change code below this line",
- "",
- ""
- ],
- "tail": [
- "(function(){return \"processed = \" + processed})();"
- ],
- "solutions": [
- "var processed = 0;\n\nfunction processArg(num) {\n return (num + 3) / 5;\n}\n\nprocessed = processArg(7);"
- ],
- "tests": [
- "assert(processed === 2, 'message: processed
should have a value of 2
');",
- "assert(/processed\\s*=\\s*processArg\\(\\s*7\\s*\\)\\s*;/.test(code), 'message: You should assign processArg
to processed
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Asignación con un valor retornado",
- "description": [
- "Si recuerdas de nuestra discusión de Almacenar Valores con el Operador Igual, todo a la derecha del signo igual es resuelto antes que el valor sea asignado. Esto significa que nosotros podemos tomar el valor de retorno de una función y asignarlo a una variable.",
- "Supongamos que tenemos una función pre-definida suma
la cual suma dos números, entonces: ",
- "nuestraSuma = suma(5, 12);
",
- "llamará la función suma
, la cual retornará un valor de 17
y lo asignará a la variable nuestraSuma
.",
- "Instrucciones
",
- "Llama la función processArg
con un argumento 7
y asigna su valor de retorno a la variable processed
."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/assignment-with-a-returned-value"
- },
- {
- "id": "56533eb9ac21ba0edf2244c6",
- "title": "Stand in Line",
- "description": [
- "In Computer Science a queue is an abstract Data Structure where items are kept in order. New items can be added at the back of the queue
and old items are taken off from the front of the queue
.",
- "Write a function nextInLine
which takes an array (arr
) and a number (item
) as arguments.",
- "Add the number to the end of the array, then remove the first element of the array.",
- "The nextInLine
function should then return the element that was removed."
- ],
- "releasedOn": "January 1, 2016",
- "head": [
- "var logOutput = [];",
- "var originalConsole = console",
- "function capture() {",
- " var nativeLog = console.log;",
- " console.log = function (message) {",
- " logOutput.push(message);",
- " if(nativeLog.apply) {",
- " nativeLog.apply(originalConsole, arguments);",
- " } else {",
- " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
- " nativeLog(nativeMsg);",
- " }",
- " };",
- "}",
- "",
- "function uncapture() {",
- " console.log = originalConsole.log;",
- "}",
- "",
- "capture();"
- ],
- "challengeSeed": [
- "function nextInLine(arr, item) {",
- " // Your code here",
- " ",
- " return item; // Change this line",
- "}",
- "",
- "// Test Setup",
- "var testArr = [1,2,3,4,5];",
- "",
- "// Display Code",
- "console.log(\"Before: \" + JSON.stringify(testArr));",
- "console.log(nextInLine(testArr, 6)); // Modify this line to test",
- "console.log(\"After: \" + JSON.stringify(testArr));"
- ],
- "tail": [
- "uncapture();",
- "testArr = [1,2,3,4,5];",
- "(function() { return logOutput.join(\"\\n\");})();"
- ],
- "solutions": [
- "var testArr = [ 1,2,3,4,5];\n\nfunction nextInLine(arr, item) {\n arr.push(item);\n return arr.shift();\n}"
- ],
- "tests": [
- "assert.isNumber(nextInLine([],5), 'message: nextInLine([], 5)
should return a number.');",
- "assert(nextInLine([],1) === 1, 'message: nextInLine([], 1)
should return 1
');",
- "assert(nextInLine([2],1) === 2, 'message: nextInLine([2], 1)
should return 2
');",
- "assert(nextInLine([5,6,7,8,9],1) === 5, 'message: nextInLine([5,6,7,8,9], 1)
should return 5
');",
- "nextInLine(testArr, 10); assert(testArr[4] === 10, 'message: After nextInLine(testArr, 10)
, testArr[4]
should be 10
');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Hacer cola",
- "description": [
- "En Ciencias de la Computación una cola es una Estructura de Datos abstracta donde los elementos son mantenidos en orden. Nuevos elementos pueden ser agregados en la parte trasera de la cola
y los elementos viejos son quitados desde el frente de la cola
.",
- "Escribe una función nextInLine
la cual toma un vector (arr
) y un número (item
) como argumentos. Agrega el número al final del vector, entonces retira el primer elemento del vector. La función nextInLine debe entonces devolver el elemento que se ha eliminado."
- ]
- }
- }
- },
- {
- "id": "bd7123c9c441eddfaeb5bdef",
- "title": "Understanding Boolean Values",
- "description": [
- "Another data type is the Boolean. Booleans
may only be one of two values: true
or false
. They are basically little on-off switches, where true
is \"on\" and false
is \"off.\" These two states are mutually exclusive.",
- "NoteBoolean
values are never written with quotes. The strings
\"true\"
and \"false\"
are not Boolean
and have no special meaning in JavaScript.",
- "
",
- "Modify the welcomeToBooleans
function so that it returns true
instead of false
when the run button is clicked."
- ],
- "challengeSeed": [
- "function welcomeToBooleans() {",
- "",
- "// Only change code below this line.",
- "",
- "return false; // Change this line",
- "",
- "// Only change code above this line.",
- "}"
- ],
- "tail": [
- "welcomeToBooleans();"
- ],
- "solutions": [
- "function welcomeToBooleans() {\n return true; // Change this line\n}"
- ],
- "tests": [
- "assert(typeof welcomeToBooleans() === 'boolean', 'message: The welcomeToBooleans()
function should return a boolean (true/false) value.');",
- "assert(welcomeToBooleans() === true, 'message: welcomeToBooleans()
should return true.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Entiende los valores booleanos",
- "description": [
- "En informática las estructuras de datos
son cosas que contienen datos. JavaScript tiene siete de estas. Por ejemplo, la estructura de datos Número
contiene números. ",
- "Vamos a aprender acerca de la estructura de datos más básica de todas: el Boolean
. Los booleanos sólo puede contener el valor verdadero o el valor falso. Son básicamente pequeños interruptores de encendido y apagado. ",
- "Instrucciones
",
- "Vamos a modificar nuestra función welcomeToBooleans
para que devuelva true
en lugar de false
cuando se pulse el botón de ejecución."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c12feddfaeb3bdef",
- "title": "Use Conditional Logic with If Statements",
- "description": [
- "If
statements are used to make decisions in code. The keyword if
tells JavaScript to execute the code in the curly braces under certain conditions, defined in the parentheses. These conditions are known as Boolean
conditions and they may only be true
or false
.",
- "When the condition evaluates to true
, the program executes the statement inside the curly braces. When the Boolean condition evaluates to false
, the statement inside the curly braces will not execute.",
- "Pseudocode",
- "if (condition is true) {
",
- "Example",
- "
statement is executed
}function test (myCondition) {
",
- "When
if (myCondition) {
return \"It was true\";
}
return \"It was false\";
}
test(true); // returns \"It was true\"
test(false); // returns \"It was false\"test
is called with a value of true
, the if
statement evaluates myCondition
to see if it is true
or not. Since it is true
, the function returns \"It was true\"
. When we call test
with a value of false
, myCondition
is not true
and the statement in the curly braces is not executed and the function returns \"It was false\"
.",
- "
",
- "Create an if
statement inside the function to return \"Yes, that was true\"
if the parameter wasThatTrue
is true
and return \"No, that was false\"
otherwise."
- ],
- "challengeSeed": [
- "// Example",
- "function ourTrueOrFalse(isItTrue) {",
- " if (isItTrue) { ",
- " return \"Yes, it's true\";",
- " }",
- " return \"No, it's false\";",
- "}",
- "",
- "// Setup",
- "function trueOrFalse(wasThatTrue) {",
- "",
- " // Only change code below this line.",
- " ",
- " ",
- " ",
- " // Only change code above this line.",
- "",
- "}",
- "",
- "// Change this value to test",
- "trueOrFalse(true);"
- ],
- "solutions": [
- "function trueOrFalse(wasThatTrue) {\n if (wasThatTrue) {\n return \"Yes, that was true\";\n }\n return \"No, that was false\";\n}"
- ],
- "tests": [
- "assert(typeof trueOrFalse === \"function\", 'message: trueOrFalse
should be a function');",
- "assert(typeof trueOrFalse(true) === \"string\", 'message: trueOrFalse(true)
should return a string');",
- "assert(typeof trueOrFalse(false) === \"string\", 'message: trueOrFalse(false)
should return a string');",
- "assert(trueOrFalse(true) === \"Yes, that was true\", 'message: trueOrFalse(true)
should return \"Yes, that was true\"');",
- "assert(trueOrFalse(false) === \"No, that was false\", 'message: trueOrFalse(false)
should return \"No, that was false\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usa lógica condicional con instrucciones if y else",
- "description": [
- "Podemos usar instrucciones if
(\"if\" es \"si\" en español) en JavaScript para ejecutar código sólo cuando cierta condición se cumpla.",
- "Las instrucciones if
requieren evaluar algún tipo de condición booleana.",
- "Por ejemplo:",
- "if (1 === 2) {
",
- " return true;
",
- "} else {
",
- " return false;
",
- "}
",
- "Vamos a usar la instrucción if
con else
(\"else\" puede traducirse como \"de lo contrario\") para hacer un juego de cara o sello.",
- "Instrucciones
",
- "Crea una instrucción if
con else
que retorne la cadena \"heads\"
si la variable flip
es cero, o bien que retorne \"tails\"
si la variable flip
no es cero. "
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d0",
- "title": "Comparison with the Equality Operator",
- "description": [
- "There are many Comparison Operators in JavaScript. All of these operators return a boolean true
or false
value.",
- "The most basic operator is the equality operator ==
. The equality operator compares two values and returns true
if they're equivalent or false
if they are not. Note that equality is different from assignment (=
), which assigns the value at the right of the operator to a variable in the left.",
- "function equalityTest(myVal) {
",
- "If
if (myVal == 10) {
return \"Equal\";
}
return \"Not Equal\";
}myVal
is equal to 10
, the equality operator returns true
, so the code in the curly braces will execute, and the function will return \"Equal\"
. Otherwise, the function will return \"Not Equal\"
.",
- "In order for JavaScript to compare two different data types
(for example, numbers
and strings
), it must convert one type to another. This is known as \"Type Coercion\". Once it does, however, it can compare terms as follows:",
- " 1 == 1 // true
",
- "
1 == 2 // false
1 == '1' // true
\"3\" == 3 // true
",
- "Add the equality operator
to the indicated line so that the function will return \"Equal\" when val
is equivalent to 12
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function testEqual(val) {",
- " if (val) { // Change this line",
- " return \"Equal\";",
- " }",
- " return \"Not Equal\";",
- "}",
- "",
- "// Change this value to test",
- "testEqual(10);"
- ],
- "solutions": [
- "function testEqual(val) {\n if (val == 12) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}"
- ],
- "tests": [
- "assert(testEqual(10) === \"Not Equal\", 'message: testEqual(10)
should return \"Not Equal\"');",
- "assert(testEqual(12) === \"Equal\", 'message: testEqual(12)
should return \"Equal\"');",
- "assert(testEqual(\"12\") === \"Equal\", 'message: testEqual(\"12\")
should return \"Equal\"');",
- "assert(code.match(/==/g) && !code.match(/===/g), 'message: You should use the ==
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador de igualdad",
- "description": [
- "Hay muchos Operadores de Comparación en JavaScript. Todos estos operadores retornan un valor booleano true
(verdadero) o false
(falso).",
- "El operador más básico es el operador de igualdad ==
. El operador de igualdad compara dos valores y retorna true
si son equivalentes o false
si no lo son. Nota que la igualdad es diferente de la asignación (=
), la cual asigna el valor a la derecha del operador a la variable en la izquierda.",
- "function pruebaIgualdad(miVal) {
",
- "Si
if (miVal == 10) {
return \"Igual\";
}
return \"No Es Igual\";
}miVal
es igual a 10
, el operador de igualdad retornará true
(verdadero), así el código entre llaves será ejecutado y la función retornará \"Equal\"
. De otra manera, la función retornará \"Not Equal\"
.",
- "Para que JavaScript pueda comparar dos tipos de datos
diferentes (por ejemplo, números
y cadenas de texto
), debe convertir un tipo a otro. Una vez que lo hace, sin embargo, puede comparar términos de la siguiente manera:",
- " 1 == 1 // true
",
- "
1 == 2 // false
1 == '1' // true
\"3\" == 3 // trueInstrucciones
",
- "Agrega el operador de igualdad
a la línea indicada de manera que la función retornará \"Equal\" cuando val
sea equivalente a 12
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d1",
- "title": "Comparison with the Strict Equality Operator",
- "description": [
- "Strict equality (===
) is the counterpart to the equality operator (==
). However, unlike the equality operator, which attempts to convert both values being compared to a common type, the strict equality operator does not perform a type conversion.",
- "If the values being compared have different types, they are considered unequal, and the strict equality operator will return false.",
- "Examples",
- "3 === 3 // true
",
- "In the second example,
3 === '3' // false3
is a Number
type and '3'
is a String
type.",
- "
",
- "Use the strict equality operator in the if
statement so the function will return \"Equal\" when val
is strictly equal to 7
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function testStrict(val) {",
- " if (val) { // Change this line",
- " return \"Equal\";",
- " }",
- " return \"Not Equal\";",
- "}",
- "",
- "// Change this value to test",
- "testStrict(10);"
- ],
- "solutions": [
- "function testStrict(val) {\n if (val === 7) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}"
- ],
- "tests": [
- "assert(testStrict(10) === \"Not Equal\", 'message: testStrict(10)
should return \"Not Equal\"');",
- "assert(testStrict(7) === \"Equal\", 'message: testStrict(7)
should return \"Equal\"');",
- "assert(testStrict(\"7\") === \"Not Equal\", 'message: testStrict(\"7\")
should return \"Not Equal\"');",
- "assert(code.match(/(val\\s*===\\s*\\d+)|(\\d+\\s*===\\s*val)/g).length > 0, 'message: You should use the ===
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador de estricta igualdad",
- "description": [
- "Igualdad estricta (===
) es la contraparte del operador de igualdad (==
). Diferente al operador de igualdad, igualdad estricta prueba los tipos de datos
y el valor de los elementos comparados.",
- "Ejemplos",
- "3 === 3 // true
",
- "En el segundo ejemplo,
3 === '3' // falso3
es de tipo Número
y '3'
es de tipo Cadena
.",
- "Instrucciones
",
- "Usa el operador de igualdad estricta en la sentencia if
de manera que la función retorne \"Equal\" cuando val
es estrictamente igual a 7
"
- ]
- }
- }
- },
- {
- "id": "599a789b454f2bbd91a3ff4d",
- "title": "Practice comparing different values",
- "description": [
- "In the last two challenges, we learned about the equality operator (==
) and the strict equality operator (===
). Let's do a quick review and practice using these operators some more.",
- "If the values being compared are not of the same type, the equality operator will perform a type conversion, and then evaluate the values. However, the strict equalty operator will compare both the data type and value as-is, without converting one type to the other.",
- "Examples",
- "3 == '3' // returns true because JavaScript performs type converstion from string to number
",
- "Note
3 === '3' // returns false because the types are different and type conversion is not performed
In JavaScript, you can determine the type of a variable or a value with the typeof
operator, as follows:",
- "typeof 3 // returns 'number'
",
- "
typeof '3' // returns 'string'
",
- "The compareEquality
function in the editor compares two values using the equality operator
. Modify the function so that it returns \"Equal\" only when the values are strictly equal."
- ],
- "releasedOn": "August 21, 2017",
- "challengeSeed": [
- "// Setup",
- "function compareEquality(a, b) {",
- " if (a == b) { // Change this line",
- " return \"Equal\";",
- " }",
- " return \"Not Equal\";",
- "}",
- "",
- "// Change this value to test",
- "compareEquality(10, \"10\");"
- ],
- "solutions": [
- "function compareEquality(a,b) {\n if (a === b) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}"
- ],
- "tests": [
- "assert(compareEquality(10, \"10\") === \"Not Equal\", 'message: compareEquality(10, \"10\")
should return \"Not Equal\"');",
- "assert(compareEquality(\"20\", 20) === \"Not Equal\", 'message: compareEquality(\"20\", 20)
should return \"Not Equal\"');",
- "assert(code.match(/===/g), 'message: You should use the ===
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "56533eb9ac21ba0edf2244d2",
- "title": "Comparison with the Inequality Operator",
- "description": [
- "The inequality operator (!=
) is the opposite of the equality operator. It means \"Not Equal\" and returns false
where equality would return true
and vice versa. Like the equality operator, the inequality operator will convert data types of values while comparing.",
- "Examples",
- "1 != 2 // true
",
- "
1 != \"1\" // false
1 != '1' // false
1 != true // false
0 != false // false
",
- "Add the inequality operator !=
in the if
statement so that the function will return \"Not Equal\" when val
is not equivalent to 99
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function testNotEqual(val) {",
- " if (val) { // Change this line",
- " return \"Not Equal\";",
- " }",
- " return \"Equal\";",
- "}",
- "",
- "// Change this value to test",
- "testNotEqual(10);"
- ],
- "solutions": [
- "function testNotEqual(val) {\n if (val != 99) {\n return \"Not Equal\";\n }\n return \"Equal\";\n}"
- ],
- "tests": [
- "assert(testNotEqual(99) === \"Equal\", 'message: testNotEqual(99)
should return \"Equal\"');",
- "assert(testNotEqual(\"99\") === \"Equal\", 'message: testNotEqual(\"99\")
should return \"Equal\"');",
- "assert(testNotEqual(12) === \"Not Equal\", 'message: testNotEqual(12)
should return \"Not Equal\"');",
- "assert(testNotEqual(\"12\") === \"Not Equal\", 'message: testNotEqual(\"12\")
should return \"Not Equal\"');",
- "assert(testNotEqual(\"bob\") === \"Not Equal\", 'message: testNotEqual(\"bob\")
should return \"Not Equal\"');",
- "assert(code.match(/(?!!==)!=/), 'message: You should use the !=
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador de desigualdad",
- "description": [
- "El operador de desigualdad (!=
) es el opuesto al operador de igualdad. Esto significa \"No Igual a\" y retorna false
cuando igualdad retornaría true
y viceversa. Como el operador de igualdad, el operador de desigualdad convertirá tipos de datos mientras compara.",
- "Ejemplos",
- "1 != 2 // true
",
- "
1 != \"1\" // false
1 != '1' // false
1 != true // false
0 != false // falseInstrucciones
",
- "Agrega el operador de desigualdad !=
en la sentencia if
de manera que la función retorne \"Not Equal\" (No igual a) cuando val
no es equivalente a 99
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d3",
- "title": "Comparison with the Strict Inequality Operator",
- "description": [
- "The strict inequality operator (!==
) is the logical opposite of the strict equality operator. It means \"Strictly Not Equal\" and returns false
where strict equality would return true
and vice versa. Strict inequality will not convert data types.",
- "Examples",
- "3 !== 3 // false
",
- "
3 !== '3' // true
4 !== 3 // true
",
- "Add the strict inequality operator
to the if
statement so the function will return \"Not Equal\" when val
is not strictly equal to 17
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function testStrictNotEqual(val) {",
- " // Only Change Code Below this Line",
- " ",
- " if (val) {",
- "",
- " // Only Change Code Above this Line",
- "",
- " return \"Not Equal\";",
- " }",
- " return \"Equal\";",
- "}",
- "",
- "// Change this value to test",
- "testStrictNotEqual(10);"
- ],
- "solutions": [
- "function testStrictNotEqual(val) {\n if (val !== 17) {\n return \"Not Equal\";\n }\n return \"Equal\";\n}"
- ],
- "MDNlinks": [
- "Strict Inequality Operator"
- ],
- "tests": [
- "assert(testStrictNotEqual(17) === \"Equal\", 'message: testStrictNotEqual(17)
should return \"Equal\"');",
- "assert(testStrictNotEqual(\"17\") === \"Not Equal\", 'message: testStrictNotEqual(\"17\")
should return \"Not Equal\"');",
- "assert(testStrictNotEqual(12) === \"Not Equal\", 'message: testStrictNotEqual(12)
should return \"Not Equal\"');",
- "assert(testStrictNotEqual(\"bob\") === \"Not Equal\", 'message: testStrictNotEqual(\"bob\")
should return \"Not Equal\"');",
- "assert(code.match(/(val\\s*!==\\s*\\d+)|(\\d+\\s*!==\\s*val)/g).length > 0, 'message: You should use the !==
operator');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador de estricta desigualdad",
- "description": [
- "El operador de estricta desigualdad (!==
) es el opuesto al operador de estricta igualdad. Esto significa \"Estrictamente no Igual\" y retorna false
(falso) donde igualdad estricta retornaría true
(verdadero) y viceversa. Estricta desigualdad no convertirá tipos de datos.",
- "Ejemplos",
- "3 !== 3 // false
",
- "
3 !== '3' // true
4 !== 3 // trueInstrucciones
",
- "Agrega el operador de estricta desigualdad
a la sentencia if
de manera que la función retorne \"Not Equal\" cuando val
no es estrictamente igual a 17
"
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d4",
- "title": "Comparison with the Greater Than Operator",
- "description": [
- "The greater than operator (>
) compares the values of two numbers. If the number to the left is greater than the number to the right, it returns true
. Otherwise, it returns false
.",
- "Like the equality operator, greater than operator will convert data types of values while comparing.",
- "Examples",
- " 5 > 3 // true
",
- "
7 > '3' // true
2 > 3 // false
'1' > 9 // false
",
- "Add the greater than
operator to the indicated lines so that the return statements make sense."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testGreaterThan(val) {",
- " if (val) { // Change this line",
- " return \"Over 100\";",
- " }",
- " ",
- " if (val) { // Change this line",
- " return \"Over 10\";",
- " }",
- "",
- " return \"10 or Under\";",
- "}",
- "",
- "// Change this value to test",
- "testGreaterThan(10);"
- ],
- "solutions": [
- "function testGreaterThan(val) {\n if (val > 100) { // Change this line\n return \"Over 100\";\n }\n if (val > 10) { // Change this line\n return \"Over 10\";\n }\n return \"10 or Under\";\n}"
- ],
- "tests": [
- "assert(testGreaterThan(0) === \"10 or Under\", 'message: testGreaterThan(0)
should return \"10 or Under\"');",
- "assert(testGreaterThan(10) === \"10 or Under\", 'message: testGreaterThan(10)
should return \"10 or Under\"');",
- "assert(testGreaterThan(11) === \"Over 10\", 'message: testGreaterThan(11)
should return \"Over 10\"');",
- "assert(testGreaterThan(99) === \"Over 10\", 'message: testGreaterThan(99)
should return \"Over 10\"');",
- "assert(testGreaterThan(100) === \"Over 10\", 'message: testGreaterThan(100)
should return \"Over 10\"');",
- "assert(testGreaterThan(101) === \"Over 100\", 'message: testGreaterThan(101)
should return \"Over 100\"');",
- "assert(testGreaterThan(150) === \"Over 100\", 'message: testGreaterThan(150)
should return \"Over 100\"');",
- "assert(code.match(/val\\s*>\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the >
operator at least twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador mayor que",
- "description": [
- "El operador mayor que (>
) compara los valores de dos números. Si el número a la izquierda es mayor que el número a la derecha, este returna true
(verdadero). De otra manera, este retorna false
(falso).",
- "Al igual que el operador de igualdad, el operador mayor que convertirá tipos de datos de valores mientras los compara.",
- "Ejemplos",
- " 5 > 3 // true
",
- "
7 > '3' // true
2 > 3 // false
'1' > 9 // falseInstrucciones
",
- "Agrega el operador mayor que
para las líneas indicadas de manera que las sentencias retornadas tengan sentido."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d5",
- "title": "Comparison with the Greater Than Or Equal To Operator",
- "description": [
- "The greater than or equal to
operator (>=
) compares the values of two numbers. If the number to the left is greater than or equal to the number to the right, it returns true
. Otherwise, it returns false
.",
- "Like the equality operator, greater than or equal to
operator will convert data types while comparing.",
- "Examples",
- " 6 >= 6 // true
",
- "
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // false
",
- "Add the greater than or equal to
operator to the indicated lines so that the return statements make sense."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testGreaterOrEqual(val) {",
- " if (val) { // Change this line",
- " return \"20 or Over\";",
- " }",
- " ",
- " if (val) { // Change this line",
- " return \"10 or Over\";",
- " }",
- "",
- " return \"Less than 10\";",
- "}",
- "",
- "// Change this value to test",
- "testGreaterOrEqual(10);"
- ],
- "solutions": [
- "function testGreaterOrEqual(val) {\n if (val >= 20) { // Change this line\n return \"20 or Over\";\n }\n \n if (val >= 10) { // Change this line\n return \"10 or Over\";\n }\n\n return \"Less than 10\";\n}"
- ],
- "tests": [
- "assert(testGreaterOrEqual(0) === \"Less than 10\", 'message: testGreaterOrEqual(0)
should return \"Less than 10\"');",
- "assert(testGreaterOrEqual(9) === \"Less than 10\", 'message: testGreaterOrEqual(9)
should return \"Less than 10\"');",
- "assert(testGreaterOrEqual(10) === \"10 or Over\", 'message: testGreaterOrEqual(10)
should return \"10 or Over\"');",
- "assert(testGreaterOrEqual(11) === \"10 or Over\", 'message: testGreaterOrEqual(11)
should return \"10 or Over\"');",
- "assert(testGreaterOrEqual(19) === \"10 or Over\", 'message: testGreaterOrEqual(19)
should return \"10 or Over\"');",
- "assert(testGreaterOrEqual(100) === \"20 or Over\", 'message: testGreaterOrEqual(100)
should return \"20 or Over\"');",
- "assert(testGreaterOrEqual(21) === \"20 or Over\", 'message: testGreaterOrEqual(21)
should return \"20 or Over\"');",
- "assert(code.match(/val\\s*>=\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the >=
operator at least twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador mayor o ogual",
- "description": [
- "El operador mayor o igual
(>=
) compara los valores de dos números. Si el número de la izquierda es mayor o igual a el número de la derecha, este retorna true
(verdadero). De otra manera, este retorna false
(falso).",
- "Como el operador de igualdad, el operador mayor o igual
convertirá tipos de datos mientras está comparando.",
- "Ejemplos",
- " 6 >= 6 // true
",
- "
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // falseInstrucciones
",
- "Agrega el operador mayor o igual
a las líneas indicadas de manera que las sentencias de retorno tengan sentido."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d6",
- "title": "Comparison with the Less Than Operator",
- "description": [
- "The less than operator (<
) compares the values of two numbers. If the number to the left is less than the number to the right, it returns true
. Otherwise, it returns false
. Like the equality operator, less than operator converts data types while comparing.",
- "Examples",
- " 2 < 5 // true
",
- "
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // false
",
- "Add the less than
operator to the indicated lines so that the return statements make sense."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testLessThan(val) {",
- " if (val) { // Change this line",
- " return \"Under 25\";",
- " }",
- " ",
- " if (val) { // Change this line",
- " return \"Under 55\";",
- " }",
- "",
- " return \"55 or Over\";",
- "}",
- "",
- "// Change this value to test",
- "testLessThan(10);"
- ],
- "solutions": [
- "function testLessThan(val) {\n if (val < 25) { // Change this line\n return \"Under 25\";\n }\n \n if (val < 55) { // Change this line\n return \"Under 55\";\n }\n\n return \"55 or Over\";\n}"
- ],
- "tests": [
- "assert(testLessThan(0) === \"Under 25\", 'message: testLessThan(0)
should return \"Under 25\"');",
- "assert(testLessThan(24) === \"Under 25\", 'message: testLessThan(24)
should return \"Under 25\"');",
- "assert(testLessThan(25) === \"Under 55\", 'message: testLessThan(25)
should return \"Under 55\"');",
- "assert(testLessThan(54) === \"Under 55\", 'message: testLessThan(54)
should return \"Under 55\"');",
- "assert(testLessThan(55) === \"55 or Over\", 'message: testLessThan(55)
should return \"55 or Over\"');",
- "assert(testLessThan(99) === \"55 or Over\", 'message: testLessThan(99)
should return \"55 or Over\"');",
- "assert(code.match(/val\\s*<\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the <
operator at least twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador menor que",
- "description": [
- "El operador menor que (<
) compara los valores de dos números. Si el número a la izquierda es menor que el número de la derecha, este retorna true
(verdadero). De otra manera, este retorna false
(falso). Como el operador de igualdad, el operador menor que convierte tipos de datos mientra compara.",
- "Ejemplos",
- " 2 < 5 // true
",
- "
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // falseInstrucciones
",
- "Agregar el operador menor que
a las líneas indicadas de modo que las sentencias de retorno tengan sentido."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d7",
- "title": "Comparison with the Less Than Or Equal To Operator",
- "description": [
- "The less than or equal to
operator (<=
) compares the values of two numbers. If the number to the left is less than or equal to the number to the right, it returns true
. If the number on the left is greater than the number on the right, it returns false
. Like the equality operator, less than or equal to
converts data types.",
- "Examples",
- " 4 <= 5 // true
",
- "
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // false
",
- "Add the less than or equal to
operator to the indicated lines so that the return statements make sense."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testLessOrEqual(val) {",
- " if (val) { // Change this line",
- " return \"Smaller Than or Equal to 12\";",
- " }",
- " ",
- " if (val) { // Change this line",
- " return \"Smaller Than or Equal to 24\";",
- " }",
- "",
- " return \"More Than 24\";",
- "}",
- "",
- "// Change this value to test",
- "testLessOrEqual(10);",
- ""
- ],
- "solutions": [
- "function testLessOrEqual(val) {\n if (val <= 12) { // Change this line\n return \"Smaller Than or Equal to 12\";\n }\n \n if (val <= 24) { // Change this line\n return \"Smaller Than or Equal to 24\";\n }\n\n return \"More Than 24\";\n}"
- ],
- "tests": [
- "assert(testLessOrEqual(0) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(0)
should return \"Smaller Than or Equal to 12\"');",
- "assert(testLessOrEqual(11) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(11)
should return \"Smaller Than or Equal to 12\"');",
- "assert(testLessOrEqual(12) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(12)
should return \"Smaller Than or Equal to 12\"');",
- "assert(testLessOrEqual(23) === \"Smaller Than or Equal to 24\", 'message: testLessOrEqual(23)
should return \"Smaller Than or Equal to 24\"');",
- "assert(testLessOrEqual(24) === \"Smaller Than or Equal to 24\", 'message: testLessOrEqual(24)
should return \"Smaller Than or Equal to 24\"');",
- "assert(testLessOrEqual(25) === \"More Than 24\", 'message: testLessOrEqual(25)
should return \"More Than 24\"');",
- "assert(testLessOrEqual(55) === \"More Than 24\", 'message: testLessOrEqual(55)
should return \"More Than 24\"');",
- "assert(code.match(/val\\s*<=\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the <=
operator at least twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador menor o igual",
- "description": [
- "El operador menor o igual
(<=
) compara los valores de dos números. Si el número a la izquierda es menor o igual que el número de la derecha, este retorna true
(verdadero). Si el número a la izquierda es mayor que el número de la derecha, este retorna false
(falso). Al igual que el operador de igualdad, menor o igual
convierte tipos de datos.",
- "Ejemplos",
- " 4 <= 5 // true
",
- "
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // falseInstrucciones
",
- "Agrega el operador menor o igual
a las líneas indicadas de modo que las sentencias de retorno tengan sentido."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d8",
- "title": "Comparisons with the Logical And Operator",
- "description": [
- "Sometimes you will need to test more than one thing at a time. The logical and operator (&&
) returns true
if and only if the operands to the left and right of it are true.",
- "The same effect could be achieved by nesting an if statement inside another if:",
- "if (num > 5) {
",
- "will only return \"Yes\" if
if (num < 10) {
return \"Yes\";
}
}
return \"No\";num
is greater than 5
and less than 10
. The same logic can be written as:",
- "if (num > 5 && num < 10) {
",
- "
return \"Yes\";
}
return \"No\";
",
- "Combine the two if statements into one statement which will return \"Yes\"
if val
is less than or equal to 50
and greater than or equal to 25
. Otherwise, will return \"No\"
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testLogicalAnd(val) {",
- " // Only change code below this line",
- "",
- " if (val) {",
- " if (val) {",
- " return \"Yes\";",
- " }",
- " }",
- "",
- " // Only change code above this line",
- " return \"No\";",
- "}",
- "",
- "// Change this value to test",
- "testLogicalAnd(10);"
- ],
- "solutions": [
- "function testLogicalAnd(val) {\n if (val >= 25 && val <= 50) {\n return \"Yes\";\n }\n return \"No\";\n}"
- ],
- "tests": [
- "assert(code.match(/&&/g).length === 1, 'message: You should use the &&
operator once');",
- "assert(code.match(/if/g).length === 1, 'message: You should only have one if
statement');",
- "assert(testLogicalAnd(0) === \"No\", 'message: testLogicalAnd(0)
should return \"No\"');",
- "assert(testLogicalAnd(24) === \"No\", 'message: testLogicalAnd(24)
should return \"No\"');",
- "assert(testLogicalAnd(25) === \"Yes\", 'message: testLogicalAnd(25)
should return \"Yes\"');",
- "assert(testLogicalAnd(30) === \"Yes\", 'message: testLogicalAnd(30)
should return \"Yes\"');",
- "assert(testLogicalAnd(50) === \"Yes\", 'message: testLogicalAnd(50)
should return \"Yes\"');",
- "assert(testLogicalAnd(51) === \"No\", 'message: testLogicalAnd(51)
should return \"No\"');",
- "assert(testLogicalAnd(75) === \"No\", 'message: testLogicalAnd(75)
should return \"No\"');",
- "assert(testLogicalAnd(80) === \"No\", 'message: testLogicalAnd(80)
should return \"No\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador lógico y",
- "description": [
- "A veces necesitarás probar más de una cosa a la vez. El operador lógico y (&&
) retorna true
(verdadero) si y solo si los operandos a la izquierda y derecha de este son verdaderos.",
- "El mismo efecto podría lograrse anidando una sentencia if dentro de otro if:",
- "if (num > 5) {
",
- "solo retornará \"Yes\" si
if (num < 10) {
return \"Yes\";
}
}
return \"No\";num
está entre 6
y 9
(6 y 9 incluidos). La misma lógica puede ser escrita como:",
- "if (num > 5 && num < 10) {
",
- "
return \"Yes\";
}
return \"No\";Instrucciones
",
- "Combina las dos sentencias if dentro de una sentencia la cual retornará \"Yes\"
si val
es menor o igual a 50
y mayor o igual a 25
. De otra manera, retornará \"No\"
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244d9",
- "title": "Comparisons with the Logical Or Operator",
- "description": [
- "The logical or operator (||
) returns true
if either of the operands is true
. Otherwise, it returns false
.",
- "The logical or operator is composed of two pipe symbols (|
). This can typically be found between your Backspace and Enter keys.",
- "The pattern below should look familiar from prior waypoints:",
- "if (num > 10) {
",
- "will return \"Yes\" only if
return \"No\";
}
if (num < 5) {
return \"No\";
}
return \"Yes\";num
is between 5
and 10
(5 and 10 included). The same logic can be written as:",
- "if (num > 10 || num < 5) {
",
- "
return \"No\";
}
return \"Yes\";
",
- "Combine the two if
statements into one statement which returns \"Outside\"
if val
is not between 10
and 20
, inclusive. Otherwise, return \"Inside\"
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testLogicalOr(val) {",
- " // Only change code below this line",
- "",
- " if (val) {",
- " return \"Outside\";",
- " }",
- "",
- " if (val) {",
- " return \"Outside\";",
- " }",
- "",
- " // Only change code above this line",
- " return \"Inside\";",
- "}",
- "",
- "// Change this value to test",
- "testLogicalOr(15);"
- ],
- "solutions": [
- "function testLogicalOr(val) {\n if (val < 10 || val > 20) {\n return \"Outside\";\n }\n return \"Inside\";\n}"
- ],
- "tests": [
- "assert(code.match(/\\|\\|/g).length === 1, 'message: You should use the ||
operator once');",
- "assert(code.match(/if/g).length === 1, 'message: You should only have one if
statement');",
- "assert(testLogicalOr(0) === \"Outside\", 'message: testLogicalOr(0)
should return \"Outside\"');",
- "assert(testLogicalOr(9) === \"Outside\", 'message: testLogicalOr(9)
should return \"Outside\"');",
- "assert(testLogicalOr(10) === \"Inside\", 'message: testLogicalOr(10)
should return \"Inside\"');",
- "assert(testLogicalOr(15) === \"Inside\", 'message: testLogicalOr(15)
should return \"Inside\"');",
- "assert(testLogicalOr(19) === \"Inside\", 'message: testLogicalOr(19)
should return \"Inside\"');",
- "assert(testLogicalOr(20) === \"Inside\", 'message: testLogicalOr(20)
should return \"Inside\"');",
- "assert(testLogicalOr(21) === \"Outside\", 'message: testLogicalOr(21)
should return \"Outside\"');",
- "assert(testLogicalOr(25) === \"Outside\", 'message: testLogicalOr(25)
should return \"Outside\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "La comparación con el operador lógico o",
- "description": [
- "El operador lógico o (||
) retorna true
(verdadero) si cualquiera de los operandos es true
(verdadero). De otra manera, este retorna false
(falso).",
- "El patrón de abajo debería ser familiar de los puntos de referencia anteriores:",
- "if (num > 10) {
",
- "retornará \"Yes\" solo si
return \"No\";
}
if (num < 5) {
return \"No\";
}
return \"Yes\";num
está entre 5
y 10
(5 y 10 incluidos). La misma lógica puede ser escrita como:",
- "if (num > 10 || num < 5) {
",
- "
return \"No\";
}
return \"Yes\";Instrucciones
",
- "Combina las dos sentencias if
dentro de una sentencia la cual retorne \"Outside\"
si val
no está entre 10
y 20
, inclusive. De otra manera, retorna \"Inside\"
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244da",
- "title": "Introducing Else Statements",
- "description": [
- "When a condition for an if
statement is true, the block of code following it is executed. What about when that condition is false? Normally nothing would happen. With an else
statement, an alternate block of code can be executed.",
- "if (num > 10) {
",
- "
return \"Bigger than 10\";
} else {
return \"10 or Less\";
}
",
- "Combine the if
statements into a single if/else
statement."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testElse(val) {",
- " var result = \"\";",
- " // Only change code below this line",
- " ",
- " if (val > 5) {",
- " result = \"Bigger than 5\";",
- " }",
- " ",
- " if (val <= 5) {",
- " result = \"5 or Smaller\";",
- " }",
- " ",
- " // Only change code above this line",
- " return result;",
- "}",
- "",
- "// Change this value to test",
- "testElse(4);",
- ""
- ],
- "solutions": [
- "function testElse(val) {\n var result = \"\";\n if(val > 5) {\n result = \"Bigger than 5\";\n } else {\n result = \"5 or Smaller\";\n }\n return result;\n}"
- ],
- "tests": [
- "assert(code.match(/if/g).length === 1, 'message: You should only have one if
statement in the editor');",
- "assert(/else/g.test(code), 'message: You should use an else
statement');",
- "assert(testElse(4) === \"5 or Smaller\", 'message: testElse(4)
should return \"5 or Smaller\"');",
- "assert(testElse(5) === \"5 or Smaller\", 'message: testElse(5)
should return \"5 or Smaller\"');",
- "assert(testElse(6) === \"Bigger than 5\", 'message: testElse(6)
should return \"Bigger than 5\"');",
- "assert(testElse(10) === \"Bigger than 5\", 'message: testElse(10)
should return \"Bigger than 5\"');",
- "assert(/var result = \"\";/.test(code) && /return result;/.test(code), 'message: Do not change the code above or below the lines.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Introducción de las sentencias else",
- "description": [
- "Cuando una condición de una sentencia if
es verdadera, el siguiente bloque de código es ejecutado. ¿Y cuando esa condición es falsa? Normalmente nada pasaría. Con una sentencia else
(además), un bloque alternativo de código puede ser ejecutado.",
- "if (num > 10) {
",
- "
return \"Más grande que 10\";
} else {
return \"10 o Menos\";
}Instrucciones
",
- "Combina las sentencias if
dentro de una sola sentencia if/else
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244db",
- "title": "Introducing Else If Statements",
- "description": [
- "If you have multiple conditions that need to be addressed, you can chain if
statements together with else if
statements.",
- "if (num > 15) {
",
- "
return \"Bigger than 15\";
} else if (num < 5) {
return \"Smaller than 5\";
} else {
return \"Between 5 and 15\";
}
",
- "Convert the logic to use else if
statements."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testElseIf(val) {",
- " if (val > 10) {",
- " return \"Greater than 10\";",
- " }",
- " ",
- " if (val < 5) {",
- " return \"Smaller than 5\";",
- " }",
- " ",
- " return \"Between 5 and 10\";",
- "}",
- "",
- "// Change this value to test",
- "testElseIf(7);",
- ""
- ],
- "solutions": [
- "function testElseIf(val) {\n if(val > 10) {\n return \"Greater than 10\";\n } else if(val < 5) {\n return \"Smaller than 5\";\n } else {\n return \"Between 5 and 10\";\n }\n}"
- ],
- "tests": [
- "assert(code.match(/else/g).length > 1, 'message: You should have at least two else
statements');",
- "assert(code.match(/if/g).length > 1, 'message: You should have at least two if
statements');",
- "assert(testElseIf(0) === \"Smaller than 5\", 'message: testElseIf(0)
should return \"Smaller than 5\"');",
- "assert(testElseIf(5) === \"Between 5 and 10\", 'message: testElseIf(5)
should return \"Between 5 and 10\"');",
- "assert(testElseIf(7) === \"Between 5 and 10\", 'message: testElseIf(7)
should return \"Between 5 and 10\"');",
- "assert(testElseIf(10) === \"Between 5 and 10\", 'message: testElseIf(10)
should return \"Between 5 and 10\"');",
- "assert(testElseIf(12) === \"Greater than 10\", 'message: testElseIf(12)
should return \"Greater than 10\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Introducción de las sentencias else if",
- "description": [
- "Si tienes múltiples condiciones que deben abordarse, puedes encadenar sentencias if
juntas con sentencias else if
.",
- "if (num > 15) {
",
- "
return \"Más grande que 15\";
} else if (num < 5) {
return \"Más pequeño que 5\";
} else {
return \"Entre 5 y 15\";
}Instrucciones
",
- "Convierte la lógica para usar sentencias else if
."
- ]
- }
- }
- },
- {
- "id": "5690307fddb111c6084545d7",
- "title": "Logical Order in If Else Statements",
- "description": [
- "Order is important in if
, else if
statements.",
- "The function is executed from top to bottom so you will want to be careful of what statement comes first.",
- "Take these two functions as an example.",
- "Here's the first:",
- "function foo(x) {
",
- "And the second just switches the order of the statements:",
- "
if (x < 1) {
return \"Less than one\";
} else if (x < 2) {
return \"Less than two\";
} else {
return \"Greater than or equal to two\";
}
}function bar(x) {
",
- "While these two functions look nearly identical if we pass a number to both we get different outputs.",
- "
if (x < 2) {
return \"Less than two\";
} else if (x < 1) {
return \"Less than one\";
} else {
return \"Greater than or equal to two\";
}
}foo(0) // \"Less than one\"
",
- "
bar(0) // \"Less than two\"
",
- "Change the order of logic in the function so that it will return the correct statements in all cases."
- ],
- "challengeSeed": [
- "function orderMyLogic(val) {",
- " if (val < 10) {",
- " return \"Less than 10\";",
- " } else if (val < 5) {",
- " return \"Less than 5\";",
- " } else {",
- " return \"Greater than or equal to 10\";",
- " }",
- "}",
- "",
- "// Change this value to test",
- "orderMyLogic(7);"
- ],
- "solutions": [
- "function orderMyLogic(val) {\n if(val < 5) {\n return \"Less than 5\"; \n } else if (val < 10) {\n return \"Less than 10\";\n } else {\n return \"Greater than or equal to 10\";\n }\n}"
- ],
- "tests": [
- "assert(orderMyLogic(4) === \"Less than 5\", 'message: orderMyLogic(4)
should return \"Less than 5\"');",
- "assert(orderMyLogic(6) === \"Less than 10\", 'message: orderMyLogic(6)
should return \"Less than 10\"');",
- "assert(orderMyLogic(11) === \"Greater than or equal to 10\", 'message: orderMyLogic(11)
should return \"Greater than or equal to 10\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Orden lógico en sentencias else if",
- "description": [
- "El orden es importante en las sentencia if
y else if
.",
- "El ciclo es ejecutado de arriba hacia abajo por lo que tendrás que ser cuidadoso de cual sentencia va primero.",
- "Toma estas dos funciones como ejemplo.",
- "Aquí está la primera:",
- "function foo(x) {
",
- "Y el segundo solo cambia el orden de las sentencias:",
- "
if (x < 1) {
return \"Menor que uno\";
} else if (x < 2) {
return \"Menor que dos\";
} else {
return \"Mayor o igual a dos\";
}
}function bar(x) {
",
- "Mientras esas dos funciones parecen casi idénticas, si nosotros pasamos un número a ambas obtendremos diferentes salidas.",
- "
if (x < 2) {
return \"Menor que dos\";
} else if (x < 1) {
return \"Menor que uno\";
} else {
return \"Mayor o igual a dos\";
}
}foo(0) // \"Menor que uno\"
",
- "
bar(0) // \"Menor que dos\"Instrucciones
",
- "Cambia el orden de la lógica en la función de manera que esta retorne las sentencias correctas en todos los casos."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244dc",
- "title": "Chaining If Else Statements",
- "description": [
- "if/else
statements can be chained together for complex logic. Here is pseudocode of multiple chained if
/ else if
statements:",
- "if (condition1) {
",
- "
statement1
} else if (condition2) {
statement2
} else if (condition3) {
statement3
. . .
} else {
statementN
}
",
- "Write chained if
/else if
statements to fulfill the following conditions:",
- "num < 5
- return \"Tiny\"num < 10
- return \"Small\"num < 15
- return \"Medium\"num < 20
- return \"Large\"num >= 20
- return \"Huge\""
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function testSize(num) {",
- " // Only change code below this line",
- " ",
- " ",
- " return \"Change Me\";",
- " // Only change code above this line",
- "}",
- "",
- "// Change this value to test",
- "testSize(7);"
- ],
- "solutions": [
- "function testSize(num) {\n if (num < 5) {\n return \"Tiny\";\n } else if (num < 10) {\n return \"Small\";\n } else if (num < 15) {\n return \"Medium\";\n } else if (num < 20) {\n return \"Large\";\n } else {\n return \"Huge\";\n }\n}"
- ],
- "tests": [
- "assert(code.match(/else/g).length > 3, 'message: You should have at least four else
statements');",
- "assert(code.match(/if/g).length > 3, 'message: You should have at least four if
statements');",
- "assert(code.match(/return/g).length >= 1, 'message: You should have at least one return
statement');",
- "assert(testSize(0) === \"Tiny\", 'message: testSize(0)
should return \"Tiny\"');",
- "assert(testSize(4) === \"Tiny\", 'message: testSize(4)
should return \"Tiny\"');",
- "assert(testSize(5) === \"Small\", 'message: testSize(5)
should return \"Small\"');",
- "assert(testSize(8) === \"Small\", 'message: testSize(8)
should return \"Small\"');",
- "assert(testSize(10) === \"Medium\", 'message: testSize(10)
should return \"Medium\"');",
- "assert(testSize(14) === \"Medium\", 'message: testSize(14)
should return \"Medium\"');",
- "assert(testSize(15) === \"Large\", 'message: testSize(15)
should return \"Large\"');",
- "assert(testSize(17) === \"Large\", 'message: testSize(17)
should return \"Large\"');",
- "assert(testSize(20) === \"Huge\", 'message: testSize(20)
should return \"Huge\"');",
- "assert(testSize(25) === \"Huge\", 'message: testSize(25)
should return \"Huge\"');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Encadenamiento de sentencias else if",
- "description": [
- "Las sentencias if/else
(si/de lo contrario) pueden ser encadenadas juntas por una lógica compleja. Aquí está el pseudocódigo de múltiples sentencias if
/ else if
encadenadas:",
- "if (condicion1) {
",
- "
sentencias1
} else if (condicion2) {
sentencias2
} else if (condicion3) {
sentencias3
. . .
} else {
sentenciasN
}Instrucciones
",
- "Escribe sentencias if
/else if
encadenadas para cumplir las siguientes condiciones:",
- "num < 5
- retorna \"Tiny\"num < 10
- retorna \"Small\"num < 15
- retorna \"Medium\"num < 20
- retorna \"Large\"num >= 20
- retorna \"Huge\""
- ]
- }
- }
- },
- {
- "id": "5664820f61c48e80c9fa476c",
- "title": "Golf Code",
- "description": [
- "In the game of golf each hole has a par
meaning the average number of strokes
a golfer is expected to make in order to sink the ball in a hole to complete the play. Depending on how far above or below par
your strokes
are, there is a different nickname.",
- "Your function will be passed par
and strokes
arguments. Return the correct string according to this table which lists the strokes in order of priority; top (highest) to bottom (lowest):",
- "
",
- "Strokes Return 1 \"Hole-in-one!\" <= par - 2 \"Eagle\" par - 1 \"Birdie\" par \"Par\" par + 1 \"Bogey\" par + 2 \"Double Bogey\" >= par + 3 \"Go Home!\" par
and strokes
will always be numeric and positive. We have added an array of all the names for your convenience."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var names = [\"Hole-in-one!\", \"Eagle\", \"Birdie\", \"Par\", \"Bogey\", \"Double Bogey\", \"Go Home!\"];",
- "function golfScore(par, strokes) {",
- " // Only change code below this line",
- " ",
- " ",
- " return \"Change Me\";",
- " // Only change code above this line",
- "}",
- "",
- "// Change these values to test",
- "golfScore(5, 4);"
- ],
- "solutions": [
- "function golfScore(par, strokes) {\n if (strokes === 1) {\n return \"Hole-in-one!\";\n }\n \n if (strokes <= par - 2) {\n return \"Eagle\";\n }\n \n if (strokes === par - 1) {\n return \"Birdie\";\n }\n \n if (strokes === par) {\n return \"Par\";\n }\n \n if (strokes === par + 1) {\n return \"Bogey\";\n }\n \n if(strokes === par + 2) {\n return \"Double Bogey\";\n }\n \n return \"Go Home!\";\n}"
- ],
- "tests": [
- "assert(golfScore(4, 1) === \"Hole-in-one!\", 'message: golfScore(4, 1)
should return \"Hole-in-one!\"');",
- "assert(golfScore(4, 2) === \"Eagle\", 'message: golfScore(4, 2)
should return \"Eagle\"');",
- "assert(golfScore(5, 2) === \"Eagle\", 'message: golfScore(5, 2)
should return \"Eagle\"');",
- "assert(golfScore(4, 3) === \"Birdie\", 'message: golfScore(4, 3)
should return \"Birdie\"');",
- "assert(golfScore(4, 4) === \"Par\", 'message: golfScore(4, 4)
should return \"Par\"');",
- "assert(golfScore(1, 1) === \"Hole-in-one!\", 'message: golfScore(1, 1)
should return \"Hole-in-one!\"');",
- "assert(golfScore(5, 5) === \"Par\", 'message: golfScore(5, 5)
should return \"Par\"');",
- "assert(golfScore(4, 5) === \"Bogey\", 'message: golfScore(4, 5)
should return \"Bogey\"');",
- "assert(golfScore(4, 6) === \"Double Bogey\", 'message: golfScore(4, 6)
should return \"Double Bogey\"');",
- "assert(golfScore(4, 7) === \"Go Home!\", 'message: golfScore(4, 7)
should return \"Go Home!\"');",
- "assert(golfScore(5, 9) === \"Go Home!\", 'message: golfScore(5, 9)
should return \"Go Home!\"');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Código de golf",
- "description": [
- "En el juego de golf cada hoyo tiene un par promedio para el número de golpes necesarios para meter la pelota. Dependiendo de que tan lejos por encima o por debajo del par
estén tus golpes
, habrá un sobrenombre diferente.",
- "Tu función pasará un par
y el número de golpes
, y retornará una cadena de acuerdo a esta tabla (basada en el orden de prioridad - arriba (lo más alto) hacia abajo (lo más bajo)):",
- "
",
- "Tanto Golpes Retorna 1 \"Hole-in-one!\" <= par - 2 \"Eagle\" par - 1 \"Birdie\" par \"Par\" par + 1 \"Bogey\" par + 2 \"Double Bogey\" >= par + 3 \"Go Home!\" par
como golpes
siempre serán numéricos y positivos."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244dd",
- "title": "Selecting from Many Options with Switch Statements",
- "description": [
- "If you have many options to choose from, use a switch
statement. A switch
statement tests a value and can have many case
statements which define various possible values. Statements are executed from the first matched case
value until a break
is encountered.",
- "Here is a pseudocode example:",
- "switch(num) {
",
- "
case value1:
statement1;
break;
case value2:
statement2;
break;
...
case valueN:
statementN;
break;
}case
values are tested with strict equality (===
). The break
tells JavaScript to stop executing statements. If the break
is omitted, the next statement will be executed.",
- "
",
- "Write a switch statement which tests val
and sets answer
for the following conditions:1
- \"alpha\"2
- \"beta\"3
- \"gamma\"4
- \"delta\""
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function caseInSwitch(val) {",
- " var answer = \"\";",
- " // Only change code below this line",
- " ",
- " ",
- " ",
- " // Only change code above this line ",
- " return answer; ",
- "}",
- "",
- "// Change this value to test",
- "caseInSwitch(1);",
- ""
- ],
- "solutions": [
- "function caseInSwitch(val) {\n var answer = \"\";\n\n switch(val) {\n case 1:\n answer = \"alpha\";\n break;\n case 2:\n answer = \"beta\";\n break;\n case 3:\n answer = \"gamma\";\n break;\n case 4:\n answer = \"delta\";\n }\n return answer; \n}"
- ],
- "tests": [
- "assert(caseInSwitch(1) === \"alpha\", 'message: caseInSwitch(1)
should have a value of \"alpha\"');",
- "assert(caseInSwitch(2) === \"beta\", 'message: caseInSwitch(2)
should have a value of \"beta\"');",
- "assert(caseInSwitch(3) === \"gamma\", 'message: caseInSwitch(3)
should have a value of \"gamma\"');",
- "assert(caseInSwitch(4) === \"delta\", 'message: caseInSwitch(4)
should have a value of \"delta\"');",
- "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if
or else
statements');",
- "assert(code.match(/break/g).length > 2, 'message: You should have at least 3 break
statements');"
- ],
- "type": "waypoint",
- "MDNlinks": [
- "Switch Statement"
- ],
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Seleccionar desde diferentes opciones con la sentencia switch",
- "description": [
- "Si tienes varias opciones para elegir, usa una sentencia switch
. Una sentencia switch
prueba un valor y puede tener varias sentencias case
las cuales definen varios posibles valores. Las sentencias son ejecutadas desde el primer valor case
igualado hasta que se encuentr un break
.",
- "Aquí hay un pseudocódigo de ejemplo:",
- "switch(num) {
",
- "Los valores
case valor1:
sentencia1;
break;
case valor2:
sentencia2;
break;
...
case valorN:
sentenciaN;
break;
}case
son probados con estricta igualdad (===
). El break
le dice a JavaScript que pare la ejecución del bloque de sentencias en el que está. Si se omite break
, se ejecutará la siguiente sentencia.",
- "Instrucciones
",
- "Escribe una sentencia switch
que pruebe val
y establezca answer
para las siguientes condiciones:1
- \"alpha\"2
- \"beta\"3
- \"gamma\"4
- \"delta\""
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244de",
- "title": "Adding a Default Option in Switch Statements",
- "description": [
- "In a switch
statement you may not be able to specify all possible values as case
statements. Instead, you can add the default
statement which will be executed if no matching case
statements are found. Think of it like the final else
statement in an if/else
chain.",
- "A default
statement should be the last case.",
- "switch (num) {
",
- "
case value1:
statement1;
break;
case value2:
statement2;
break;
...
default:
defaultStatement;
break;
}
",
- "Write a switch statement to set answer
for the following conditions:\"a\"
- \"apple\"\"b\"
- \"bird\"\"c\"
- \"cat\"default
- \"stuff\""
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function switchOfStuff(val) {",
- " var answer = \"\";",
- " // Only change code below this line",
- " ",
- " ",
- " ",
- " // Only change code above this line ",
- " return answer; ",
- "}",
- "",
- "// Change this value to test",
- "switchOfStuff(1);",
- ""
- ],
- "solutions": [
- "function switchOfStuff(val) {\n var answer = \"\";\n\n switch(val) {\n case \"a\":\n answer = \"apple\";\n break;\n case \"b\":\n answer = \"bird\";\n break;\n case \"c\":\n answer = \"cat\";\n break;\n default:\n answer = \"stuff\";\n }\n return answer; \n}"
- ],
- "tests": [
- "assert(switchOfStuff(\"a\") === \"apple\", 'message: switchOfStuff(\"a\")
should have a value of \"apple\"');",
- "assert(switchOfStuff(\"b\") === \"bird\", 'message: switchOfStuff(\"b\")
should have a value of \"bird\"');",
- "assert(switchOfStuff(\"c\") === \"cat\", 'message: switchOfStuff(\"c\")
should have a value of \"cat\"');",
- "assert(switchOfStuff(\"d\") === \"stuff\", 'message: switchOfStuff(\"d\")
should have a value of \"stuff\"');",
- "assert(switchOfStuff(4) === \"stuff\", 'message: switchOfStuff(4)
should have a value of \"stuff\"');",
- "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if
or else
statements');",
- "assert(switchOfStuff(\"string-to-trigger-default-case\") === \"stuff\", 'message: You should use a default
statement');",
- "assert(code.match(/break/g).length > 2, 'message: You should have at least 3 break
statements');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Agregar una opción por omisión (default) en una sentencia switch",
- "description": [
- "En una sentencia switch
puede que no seas capaz de especificar todos los posibles valores en las sentencias case
. En su lugar, puedes agregar la sentencia default
la cual será ejecutada si no es encontrada ninguna coincidencia con alguna sentencia case
. Piensa en esto como la última sentencia else
en una cadena if/else
.",
- "Una sentencia default
debería ser el último caso.",
- "switch(num) {
",
- "
case valor1:
sentencia1;
break;
case valor2:
sentencia2;
break;
...
default:
sentenciaDefault;
}Instrucciones
",
- "Escribe una sentencia switch para establecer answer
para las siguientes condiciones:\"a\"
- \"apple\"\"b\"
- \"bird\"\"c\"
- \"cat\"default
- \"stuff\""
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/adding-a-default-option-in-switch-statements"
- },
- {
- "id": "56533eb9ac21ba0edf2244df",
- "title": "Multiple Identical Options in Switch Statements",
- "description": [
- "If the break
statement is omitted from a switch
statement's case
, the following case
statement(s) are executed until a break
is encountered. If you have multiple inputs with the same output, you can represent them in a switch
statement like this:",
- "switch(val) {
",
- "Cases for 1, 2, and 3 will all produce the same result.",
- "
case 1:
case 2:
case 3:
result = \"1, 2, or 3\";
break;
case 4:
result = \"4 alone\";
}
",
- "Write a switch statement to set answer
for the following ranges:1-3
- \"Low\"4-6
- \"Mid\"7-9
- \"High\"",
- "Note
You will need to have a case
statement for each number in the range."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function sequentialSizes(val) {",
- " var answer = \"\";",
- " // Only change code below this line",
- " ",
- " ",
- " ",
- " // Only change code above this line ",
- " return answer; ",
- "}",
- "",
- "// Change this value to test",
- "sequentialSizes(1);",
- ""
- ],
- "solutions": [
- "function sequentialSizes(val) {\n var answer = \"\";\n \n switch(val) {\n case 1:\n case 2:\n case 3:\n answer = \"Low\";\n break;\n case 4:\n case 5:\n case 6:\n answer = \"Mid\";\n break;\n case 7:\n case 8:\n case 9:\n answer = \"High\";\n }\n \n return answer; \n}"
- ],
- "tests": [
- "assert(sequentialSizes(1) === \"Low\", 'message: sequentialSizes(1)
should return \"Low\"');",
- "assert(sequentialSizes(2) === \"Low\", 'message: sequentialSizes(2)
should return \"Low\"');",
- "assert(sequentialSizes(3) === \"Low\", 'message: sequentialSizes(3)
should return \"Low\"');",
- "assert(sequentialSizes(4) === \"Mid\", 'message: sequentialSizes(4)
should return \"Mid\"');",
- "assert(sequentialSizes(5) === \"Mid\", 'message: sequentialSizes(5)
should return \"Mid\"');",
- "assert(sequentialSizes(6) === \"Mid\", 'message: sequentialSizes(6)
should return \"Mid\"');",
- "assert(sequentialSizes(7) === \"High\", 'message: sequentialSizes(7)
should return \"High\"');",
- "assert(sequentialSizes(8) === \"High\", 'message: sequentialSizes(8)
should return \"High\"');",
- "assert(sequentialSizes(9) === \"High\", 'message: sequentialSizes(9)
should return \"High\"');",
- "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if
or else
statements');",
- "assert(code.match(/case/g).length === 9, 'message: You should have nine case
statements');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Múltiples opciones idénticas en una sentencias switch",
- "description": [
- "Si la sentencia break
es omitida de una sentencia case
de un switch
, las siguientes sentencias case
son ejecutadas hasta que sea encontrado un break
. Si tienes multiples entradas con la misma salida, puede representarlas en una sentencia switch
así:",
- "switch(val) {
",
- "Los casos 1, 2, y 3 producirán el mismo resultado.",
- "
case 1:
case 2:
case 3:
result = \"1, 2, or 3\";
break;
case 4:
result = \"4 alone\";
}Instrucciones
",
- "Escribe una sentencia switch
para establecer answer
para los siguientes rangos:1-3
- \"Low\"4-6
- \"Mid\"7-9
- \"High\"",
- "Nota
Necesitarás tener una sentencia case
por cada número en el rango."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244e0",
- "title": "Replacing If Else Chains with Switch",
- "description": [
- "If you have many options to choose from, a switch
statement can be easier to write than many chained if
/else if
statements. The following:",
- "if (val === 1) {
",
- "can be replaced with:",
- "
answer = \"a\";
} else if (val === 2) {
answer = \"b\";
} else {
answer = \"c\";
}switch(val) {
",
- "
case 1:
answer = \"a\";
break;
case 2:
answer = \"b\";
break;
default:
answer = \"c\";
}
",
- "Change the chained if
/else if
statements into a switch
statement."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function chainToSwitch(val) {",
- " var answer = \"\";",
- " // Only change code below this line",
- " ",
- " if (val === \"bob\") {",
- " answer = \"Marley\";",
- " } else if (val === 42) {",
- " answer = \"The Answer\";",
- " } else if (val === 1) {",
- " answer = \"There is no #1\";",
- " } else if (val === 99) {",
- " answer = \"Missed me by this much!\";",
- " } else if (val === 7) {",
- " answer = \"Ate Nine\";",
- " }",
- " ",
- " // Only change code above this line ",
- " return answer; ",
- "}",
- "",
- "// Change this value to test",
- "chainToSwitch(7);",
- ""
- ],
- "solutions": [
- "function chainToSwitch(val) {\n var answer = \"\";\n\n switch(val) {\n case \"bob\":\n answer = \"Marley\";\n break;\n case 42:\n answer = \"The Answer\";\n break;\n case 1:\n answer = \"There is no #1\";\n break;\n case 99:\n answer = \"Missed me by this much!\";\n break;\n case 7:\n answer = \"Ate Nine\";\n }\n return answer; \n}"
- ],
- "tests": [
- "assert(!/else/g.test(code), 'message: You should not use any else
statements anywhere in the editor');",
- "assert(!/if/g.test(code), 'message: You should not use any if
statements anywhere in the editor');",
- "assert(code.match(/break/g).length >= 4, 'message: You should have at least four break
statements');",
- "assert(chainToSwitch(\"bob\") === \"Marley\", 'message: chainToSwitch(\"bob\")
should be \"Marley\"');",
- "assert(chainToSwitch(42) === \"The Answer\", 'message: chainToSwitch(42)
should be \"The Answer\"');",
- "assert(chainToSwitch(1) === \"There is no #1\", 'message: chainToSwitch(1)
should be \"There is no #1\"');",
- "assert(chainToSwitch(99) === \"Missed me by this much!\", 'message: chainToSwitch(99)
should be \"Missed me by this much!\"');",
- "assert(chainToSwitch(7) === \"Ate Nine\", 'message: chainToSwitch(7)
should be \"Ate Nine\"');",
- "assert(chainToSwitch(\"John\") === \"\", 'message: chainToSwitch(\"John\")
should be \"\" (empty string)');",
- "assert(chainToSwitch(156) === \"\", 'message: chainToSwitch(156)
should be \"\" (empty string)');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Reemplazar cadenas if else con switch",
- "description": [
- "Si tienes varias opciones para elegir, una sentencia switch
puede ser más fácil de escribir que varias sentencias if
/if else
anidadas. Lo siguiente:",
- "if (val === 1) {
",
- "puede ser reemplazado con:",
- "
respuesta = \"a\";
} else if (val === 2) {
respuesta = \"b\";
} else {
respuesta = \"c\";
}switch(val) {
",
- "
case 1:
respuesta = \"a\";
break;
case 2:
respuesta = \"b\";
break;
default:
respuesta = \"c\";
}Instrucciones
",
- "Cambia las sentencias if
/if else
anidadas dentro de una sentencia switch
."
- ]
- }
- }
- },
- {
- "id": "5679ceb97cbaa8c51670a16b",
- "title": "Returning Boolean Values from Functions",
- "description": [
- "You may recall from Comparison with the Equality Operator that all comparison operators return a boolean true
or false
value.",
- "Sometimes people use an if/else statement to do a comparison, like this:",
- "function isEqual(a,b) {
",
- "But there's a better way to do this. Since
if (a === b) {
return true;
} else {
return false;
}
}===
returns true
or false
, we can return the result of the comparison:",
- "function isEqual(a,b) {
",
- "
return a === b;
}
",
- "Fix the function isLess
to remove the if/else
statements."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function isLess(a, b) {",
- " // Fix this code",
- " if (a < b) {",
- " return true;",
- " } else {",
- " return false;",
- " }",
- "}",
- "",
- "// Change these values to test",
- "isLess(10, 15);"
- ],
- "tail": [
- ""
- ],
- "solutions": [
- "function isLess(a, b) {\n return a < b;\n}"
- ],
- "tests": [
- "assert(isLess(10,15) === true, 'message: isLess(10,15)
should return true
');",
- "assert(isLess(15, 10) === false, 'message: isLess(15,10)
should return false
');",
- "assert(!/if|else/g.test(code), 'message: You should not use any if
or else
statements');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Retornar valores booleanos desde funciones",
- "description": [
- "Tal vez recuerdes de La comparación con el operador de igualdad que todos los operadores de comparación retornan un valor booleano true
(verdadero) o false
(falso).",
- "Un anti-patrón común es usar una sentencia if/else
para hacer una comparación y entonces retornar true
o false
:",
- "function sonIguales(a,b) {
",
- "Ya que
if (a === b) {
return true;
} else {
return false;
}
}===
returna true
(verdadero) o false
(falso), podemos simplemente retornar el resultado de la comparación:",
- "function sonIguales(a,b) {
",
- "
return a === b;
}Instrucciones
",
- "Arregla la función isLess
para remover las sentencias if/else
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244c4",
- "title": "Return Early Pattern for Functions",
- "description": [
- "When a return
statement is reached, the execution of the current function stops and control returns to the calling location.",
- "Example",
- "function myFun() {
",
- "The above outputs \"Hello\" to the console, returns \"World\", but
console.log(\"Hello\");
return \"World\";
console.log(\"byebye\")
}
myFun();\"byebye\"
is never output, because the function exits at the return
statement.",
- "
",
- "Modify the function abTest
so that if a
or b
are less than 0
the function will immediately exit with a value of undefined
.",
- "Hint
Remember that undefined
is a keyword, not a string."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function abTest(a, b) {",
- " // Only change code below this line",
- " ",
- " ",
- " ",
- " // Only change code above this line",
- "",
- " return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));",
- "}",
- "",
- "// Change values below to test your code",
- "abTest(2,2);"
- ],
- "tail": [
- ""
- ],
- "solutions": [
- "function abTest(a, b) {\n if(a < 0 || b < 0) {\n return undefined;\n } \n return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));\n}"
- ],
- "tests": [
- "assert(typeof abTest(2,2) === 'number' , 'message: abTest(2,2)
should return a number');",
- "assert(abTest(2,2) === 8 , 'message: abTest(2,2)
should return 8
');",
- "assert(abTest(-2,2) === undefined , 'message: abTest(-2,2)
should return undefined
');",
- "assert(abTest(2,-2) === undefined , 'message: abTest(2,-2)
should return undefined
');",
- "assert(abTest(2,8) === 18 , 'message: abTest(2,8)
should return 18
');",
- "assert(abTest(3,3) === 12 , 'message: abTest(3,3)
should return 12
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Retornar un patrón temprano para funciones",
- "description": [
- "Cuando se alcanza una sentencia return
, la ejecución de la presente función se detiene y el control la retorna a la ubicación de la llamada.",
- "Ejemplo",
- "function miFuncion() {
",
- "Esta presenta en consola \"Hola\", retorna \"Mundo\", pero
console.log(\"Hola\");
return \"Mundo\";
console.log(\"chaochao\")
}
miFuncion();\"chaochao\"
nunca se presenta, porque la función sale con la sentencia return
.",
- "Instrucciones
",
- "Modifica la función abTest
de manera que si a
o b
son menores que 0
la función saldrá inmediatamente con un valor undefined
.",
- "Pista
Recuerda que undefined
es una palabra clave, no una cadena."
- ]
- }
- }
- },
- {
- "id": "565bbe00e9cc8ac0725390f4",
- "title": "Counting Cards",
- "description": [
- "In the casino game Blackjack, a player can gain an advantage over the house by keeping track of the relative number of high and low cards remaining in the deck. This is called Card Counting.",
- "Having more high cards remaining in the deck favors the player. Each card is assigned a value according to the table below. When the count is positive, the player should bet high. When the count is zero or negative, the player should bet low.",
- "
",
- "You will write a card counting function. It will receive a Count Change Cards +1 2, 3, 4, 5, 6 0 7, 8, 9 -1 10, 'J', 'Q', 'K', 'A' card
parameter, which can be a number or a string, and increment or decrement the global count
variable according to the card's value (see table). The function will then return a string with the current count and the string Bet
if the count is positive, or Hold
if the count is zero or negative. The current count and the player's decision (Bet
or Hold
) should be separated by a single space.",
- "Example Output-3 Hold
5 Bet
",
- "Hint
Do NOT reset count
to 0 when value is 7, 8, or 9.
Do NOT return an array.
Do NOT include quotes (single or double) in the output."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var count = 0;",
- "",
- "function cc(card) {",
- " // Only change code below this line",
- " ",
- " ",
- " return \"Change Me\";",
- " // Only change code above this line",
- "}",
- "",
- "// Add/remove calls to test your function.",
- "// Note: Only the last will display",
- "cc(2); cc(3); cc(7); cc('K'); cc('A');"
- ],
- "solutions": [
- "var count = 0;\nfunction cc(card) {\n switch(card) {\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n count++;\n break;\n case 10:\n case 'J':\n case 'Q':\n case 'K':\n case 'A':\n count--;\n }\n if(count > 0) {\n return count + \" Bet\";\n } else {\n return count + \" Hold\";\n }\n}"
- ],
- "tests": [
- "assert((function(){ count = 0; cc(2);cc(3);cc(4);cc(5);var out = cc(6); if(out === \"5 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, 3, 4, 5, 6 should return 5 Bet
');",
- "assert((function(){ count = 0; cc(7);cc(8);var out = cc(9); if(out === \"0 Hold\") {return true;} return false; })(), 'message: Cards Sequence 7, 8, 9 should return 0 Hold
');",
- "assert((function(){ count = 0; cc(10);cc('J');cc('Q');cc('K');var out = cc('A'); if(out === \"-5 Hold\") {return true;} return false; })(), 'message: Cards Sequence 10, J, Q, K, A should return -5 Hold
');",
- "assert((function(){ count = 0; cc(3);cc(7);cc('Q');cc(8);var out = cc('A'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 7, Q, 8, A should return -1 Hold
');",
- "assert((function(){ count = 0; cc(2);cc('J');cc(9);cc(2);var out = cc(7); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, J, 9, 2, 7 should return 1 Bet
');",
- "assert((function(){ count = 0; cc(2);cc(2);var out = cc(10); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, 2, 10 should return 1 Bet
');",
- "assert((function(){ count = 0; cc(3);cc(2);cc('A');cc(10);var out = cc('K'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 2, A, 10, K should return -1 Hold
');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Contar cartas",
- "description": [
- "En el juego de casino Blackjack, un jugador puede conseguir ventaja sobre la casa manteniendo un registro del número relativo de cartas altas y bajas restantes en la baraja. Esto es llamado Conteo de Cartas.",
- "Tener más cartas altas restantes en la baraja favorece al jugador. A cada carta se le asigna un valor de acuerdo a la tabla de abajo. Cuando el conteo es positivo, el jugador debe apostar alto. Cuando el conteo es cero o negativo, el jugador debe apostar bajo.",
- "
",
- "Vas a escribir una función de conteo de cartas. Esta recibirá un parametro Valor Cartas +1 2, 3, 4, 5, 6 0 7, 8, 9 -1 10, 'J', 'Q', 'K','A' card
(carta) e incrementa o decrementa la variable count
(conteo) global de acuerdo al valor de la carta (ver tabla). La función retornará entonces una cadena con el presente conteo y la cadena Bet
si el conteo es positivo o Hold
si el conteo es cero o negativo. El presente conteo y la desición del jugador (Bet
o Hold
) deben quedar separada por un único espacio.",
- "Ejemplo de Salida-3 Hold
"
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392d0",
- "title": "Build JavaScript Objects",
- "description": [
- "You may have heard the term
5 Betobject
before.",
- "Objects are similar to arrays
, except that instead of using indexes to access and modify their data, you access the data in objects through what are called properties
.",
- "Objects are useful for storing data in a structured way, and can represent real world objects, like a cat.",
- "Here's a sample cat object:",
- "var cat = {
",
- "In this example, all the properties are stored as strings, such as -
\"name\": \"Whiskers\",
\"legs\": 4,
\"tails\": 1,
\"enemies\": [\"Water\", \"Dogs\"]
};\"name\"
, \"legs\"
, and \"tails\"
. However, you can also use numbers as properties. You can even omit the quotes for single-word string properties, as follows:",
- "var anotherObject = {
",
- "However, if your object has any non-string properties, JavaScript will automatically typecast them as strings.",
- "
make: \"Ford\",
5: \"five\",
\"model\": \"focus\"
};
",
- "Make an object that represents a dog called myDog
which contains the properties \"name\"
(a string), \"legs\"
, \"tails\"
and \"friends\"
.",
- "You can set these object properties to whatever values you want, as long \"name\"
is a string, \"legs\"
and \"tails\"
are numbers, and \"friends\"
is an array."
- ],
- "challengeSeed": [
- "// Example",
- "var ourDog = {",
- " \"name\": \"Camper\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"everything!\"]",
- "};",
- "",
- "// Only change code below this line.",
- "",
- "var myDog = {",
- " ",
- " ",
- " ",
- " ",
- "};"
- ],
- "tail": [
- "(function(z){return z;})(myDog);"
- ],
- "solutions": [
- "var myDog = {\n \"name\": \"Camper\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"everything!\"] \n};"
- ],
- "tests": [
- "assert((function(z){if(z.hasOwnProperty(\"name\") && z.name !== undefined && typeof z.name === \"string\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property name
and it should be a string
.');",
- "assert((function(z){if(z.hasOwnProperty(\"legs\") && z.legs !== undefined && typeof z.legs === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property legs
and it should be a number
.');",
- "assert((function(z){if(z.hasOwnProperty(\"tails\") && z.tails !== undefined && typeof z.tails === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property tails
and it should be a number
.');",
- "assert((function(z){if(z.hasOwnProperty(\"friends\") && z.friends !== undefined && Array.isArray(z.friends)){return true;}else{return false;}})(myDog), 'message: myDog
should contain the property friends
and it should be an array
.');",
- "assert((function(z){return Object.keys(z).length === 4;})(myDog), 'message: myDog
should only contain all the given properties.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Construye objetos en JavaScript",
- "description": [
- "Es posible que haya oído el término objeto
antes.",
- "Los objetos son similares a los vectores
, excepto que en lugar de utilizar los índices para acceder y modificar sus datos, pueden accederse mediante lo que se llama propiedades
.",
- "Esto es un objeto de ejemplo:",
- "var cat = {
",
- " \"name\": \"Whiskers\",
",
- " \"legs\": 4,
",
- " \"tails\": 1,
",
- " \"enemies\": [\"Water\", \"Dogs\"]
",
- "};
",
- "Los objetos son útiles para almacenar datos de manera estructurada, y pueden representar objetos del mundo real, como un gato.",
- "Vamos a tratar de hacer un objeto que representa un perro, lo llamaremos mydog
y contendrá las propiedades \"name\"
(una cadena con el nombre), \"legs\"
(piernas), \"tails\"
(colas) y \"friends\" (amigos)
. ",
- "Podrás establecer estas propiedades del objeto en los valores que desees, siempre y cuando \"name\"
sea una cadena, \"legs\"
y \"tails\"
sean números, y \"friends\"
sea un vector."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244c7",
- "title": "Accessing Object Properties with Dot Notation",
- "description": [
- "There are two ways to access the properties of an object: dot notation (.
) and bracket notation ([]
), similar to an array.",
- "Dot notation is what you use when you know the name of the property you're trying to access ahead of time.",
- "Here is a sample of using dot notation (.
) to read an object's property:",
- "var myObj = {
",
- "
prop1: \"val1\",
prop2: \"val2\"
};
var prop1val = myObj.prop1; // val1
var prop2val = myObj.prop2; // val2
",
- "Read in the property values of testObj
using dot notation. Set the variable hatValue
equal to the object's property hat
and set the variable shirtValue
equal to the object's property shirt
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var testObj = {",
- " \"hat\": \"ballcap\",",
- " \"shirt\": \"jersey\",",
- " \"shoes\": \"cleats\"",
- "};",
- "",
- "// Only change code below this line",
- "",
- "var hatValue = testObj; // Change this line",
- "var shirtValue = testObj; // Change this line"
- ],
- "tail": [
- "(function(a,b) { return \"hatValue = '\" + a + \"', shirtValue = '\" + b + \"'\"; })(hatValue,shirtValue);"
- ],
- "solutions": [
- "var testObj = {\n \"hat\": \"ballcap\",\n \"shirt\": \"jersey\",\n \"shoes\": \"cleats\"\n};\n\nvar hatValue = testObj.hat; \nvar shirtValue = testObj.shirt;"
- ],
- "tests": [
- "assert(typeof hatValue === 'string' , 'message: hatValue
should be a string');",
- "assert(hatValue === 'ballcap' , 'message: The value of hatValue
should be \"ballcap\"
');",
- "assert(typeof shirtValue === 'string' , 'message: shirtValue
should be a string');",
- "assert(shirtValue === 'jersey' , 'message: The value of shirtValue
should be \"jersey\"
');",
- "assert(code.match(/testObj\\.\\w+/g).length > 1, 'message: You should use dot notation twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a propiedades de objetos con el operador punto",
- "description": [
- "Hay dos maneras de acceder a las propiedades de un objeto: con el operador punto (.
) y con la notación corchete ([]
), similar al caso de un vector.",
- "El operador punto es el que usas cuando de antemano sabes el nombre de la propiedad que estás intentando acceder.",
- "Aquí está un ejemplo del uso del operador punto (.
) para leer una propiedad de un objeto:",
- "var miObj = {
",
- "
prop1: \"val1\",
prop2: \"val2\"
};
var prop1val = miObj.prop1; // val1
var prop2val = miObj.prop2; // val2Instrucciones
",
- "Lee los valores de propiedades de testObj
usando notación punto. Asigna la variable hatValue
igual a la propiedad objeto hat
y asigna la variable shirtValue
igual a la propiedad objeto shirt
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244c8",
- "title": "Accessing Object Properties with Bracket Notation",
- "description": [
- "The second way to access the properties of an object is bracket notation ([]
). If the property of the object you are trying to access has a space in its name, you will need to use bracket notation.",
- "However, you can still use bracket notation on object properties without spaces.",
- "Here is a sample of using bracket notation to read an object's property:",
- "var myObj = {
",
- "Note that property names with spaces in them must be in quotes (single or double).",
- "
\"Space Name\": \"Kirk\",
\"More Space\": \"Spock\",
\"NoSpace\": \"USS Enterprise\"
};
myObj[\"Space Name\"]; // Kirk
myObj['More Space']; // Spock
myObj[\"NoSpace\"]; // USS Enterprise
",
- "Read the values of the properties \"an entree\"
and \"the drink\"
of testObj
using bracket notation and assign them to entreeValue
and drinkValue
respectively."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var testObj = {",
- " \"an entree\": \"hamburger\",",
- " \"my side\": \"veggies\",",
- " \"the drink\": \"water\"",
- "};",
- "",
- "// Only change code below this line",
- "",
- "var entreeValue = testObj; // Change this line",
- "var drinkValue = testObj; // Change this line"
- ],
- "tail": [
- "(function(a,b) { return \"entreeValue = '\" + a + \"', drinkValue = '\" + b + \"'\"; })(entreeValue,drinkValue);"
- ],
- "solutions": [
- "var testObj = {\n \"an entree\": \"hamburger\",\n \"my side\": \"veggies\",\n \"the drink\": \"water\"\n};\nvar entreeValue = testObj[\"an entree\"];\nvar drinkValue = testObj['the drink'];"
- ],
- "tests": [
- "assert(typeof entreeValue === 'string' , 'message: entreeValue
should be a string');",
- "assert(entreeValue === 'hamburger' , 'message: The value of entreeValue
should be \"hamburger\"
');",
- "assert(typeof drinkValue === 'string' , 'message: drinkValue
should be a string');",
- "assert(drinkValue === 'water' , 'message: The value of drinkValue
should be \"water\"
');",
- "assert(code.match(/testObj\\s*?\\[('|\")[^'\"]+\\1\\]/g).length > 1, 'message: You should use bracket notation twice');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a las propiedades de objetos con la notación corchete",
- "description": [
- "La segunda manera de acceder a las propiedades de un objeto es con la notación corchete ([]
). Si el nombre de la propiedad del objeto que estás intentando acceder tiene un espacio, necesitarás usar la notación corchete.",
- "Aquí está un ejemplo del uso de la notación corchete para leer una propiedad de un objeto:",
- "var miObj = {
",
- "Nota que los nombres de propiedades con espacios tienen que estar entre comillas (apóstrofes o comillas).",
- "
\"Nombre con espacio\": \"Kirk\",
\"Mas espacio\": \"Spock\"
};
miObj[\"Nombre con espacio\"]; // Kirk
miObj['Mas espacio']; // SpockInstrucciones
",
- "Lee los valores de las propiedades \"an entree\"
y \"the drink\"
de testObj
usando la notación corchete."
- ]
- }
- },
- "guideUrl": "https://guide.freecodecamp.org/certificates/accessing-objects-properties-with-bracket-notation"
- },
- {
- "id": "56533eb9ac21ba0edf2244c9",
- "title": "Accessing Object Properties with Variables",
- "description": [
- "Another use of bracket notation on objects is to access a property which is stored as the value of a variable. This can be very useful for iterating through an object's properties or when accessing a lookup table.",
- "Here is an example of using a variable to access a property:",
- "var dogs = {
",
- "Another way you can use this concept is when the property's name is collected dynamically during the program execution, as follows:",
- "
Fido: \"Mutt\",\n Hunter: \"Doberman\",\n Snoopie: \"Beagle\"
};
var myDog = \"Hunter\";
var myBreed = dogs[myDog];
console.log(myBreed); // \"Doberman\"var someObj = {
",
- "Note that we do not use quotes around the variable name when using it to access the property because we are using the value of the variable, not the name.",
- "
propName: \"John\"
};
function propPrefix(str) {
var s = \"prop\";
return s + str;
}
var someProp = propPrefix(\"Name\"); // someProp now holds the value 'propName'
console.log(someObj[someProp]); // \"John\"
",
- "Use the playerNumber
variable to look up player 16
in testObj
using bracket notation. Then assign that name to the player
variable."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var testObj = {",
- " 12: \"Namath\",",
- " 16: \"Montana\",",
- " 19: \"Unitas\"",
- "};",
- "",
- "// Only change code below this line;",
- "",
- "var playerNumber; // Change this Line",
- "var player = testObj; // Change this Line"
- ],
- "tail": [
- "if(typeof player !== \"undefined\"){(function(v){return v;})(player);}"
- ],
- "solutions": [
- "var testObj = {\n 12: \"Namath\",\n 16: \"Montana\",\n 19: \"Unitas\"\n};\nvar playerNumber = 16;\nvar player = testObj[playerNumber];"
- ],
- "tests": [
- "assert(typeof playerNumber === 'number', 'message: playerNumber
should be a number');",
- "assert(typeof player === 'string', 'message: The variable player
should be a string');",
- "assert(player === 'Montana', 'message: The value of player
should be \"Montana\"');",
- "assert(/testObj\\s*?\\[.*?\\]/.test(code),'message: You should use bracket notation to access testObj
');",
- "assert(!code.match(/player\\s*=\\s*\"|\\'\\s*Montana\\s*\"|\\'\\s*;/gi),'message: You should not assign the value Montana
to the variable player
directly.');",
- "assert(/testObj\\s*?\\[\\s*playerNumber\\s*\\]/.test(code),'message: You should be using the variable playerNumber
in your bracket notation');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a propiedades de objetos con variables",
- "description": [
- "Otro uso de la notación corchete sobre objetos es usar una variable para acceder a una propiedad. Esto puede ser muy útil en iteraciones sobre la lista de propiedades de un objetos o para hacer operaciones de búsqueda.",
- "Aquí está un ejemplo del uso de una variable para acceder a una propiedad:",
- "var algunaProp = \"propNombre\";
",
- "Aquí hay uno más:",
- "
var miObj = {
propNombre: \"Algún valor\"
}
miObj[algunaProp]; // \"Algún valor\"var miPerro = \"Cazador\";
",
- "Nota que no usamos comillas alrededor del nombre de la variable (
var perros = {
Fido: \"Mutt\",\n Cazador: \"Doberman\",\n Snoopie: \"Beagle\"
}
var raza = perros[miPerro]; // \"Cazador\"
console.log(raza)// \"Doberman\"miPerro
) cuando la usamos para acceder a la propiedad (perros[miPerro]
porque estamos usando el valor de la variable y no su nombre",
- "Instrucciones
",
- "Usa la variable playerNumber
para buscar y asignar a player
el jugador 16
de testObj
, usa la notación corchete."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/accessing-objects-properties-with-variables"
- },
- {
- "id": "56bbb991ad1ed5201cd392d1",
- "title": "Updating Object Properties",
- "description": [
- "After you've created a JavaScript object, you can update its properties at any time just like you would update any other variable. You can use either dot or bracket notation to update.",
- "For example, let's look at ourDog
:",
- "var ourDog = {
",
- "Since he's a particularly happy dog, let's change his name to \"Happy Camper\". Here's how we update his object's name property:",
- "
\"name\": \"Camper\",
\"legs\": 4,
\"tails\": 1,
\"friends\": [\"everything!\"]
};ourDog.name = \"Happy Camper\";
or",
- "ourDog[\"name\"] = \"Happy Camper\";
",
- "Now when we evaluate ourDog.name
, instead of getting \"Camper\", we'll get his new name, \"Happy Camper\".",
- "
",
- "Update the myDog
object's name property. Let's change her name from \"Coder\" to \"Happy Coder\". You can use either dot or bracket notation."
- ],
- "challengeSeed": [
- "// Example",
- "var ourDog = {",
- " \"name\": \"Camper\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"everything!\"]",
- "};",
- "",
- "ourDog.name = \"Happy Camper\";",
- "",
- "// Setup",
- "var myDog = {",
- " \"name\": \"Coder\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"freeCodeCamp Campers\"]",
- "};",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "(function(z){return z;})(myDog);"
- ],
- "solutions": [
- "var myDog = {\n \"name\": \"Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"]\n};\nmyDog.name = \"Happy Coder\";"
- ],
- "tests": [
- "assert(/happy coder/gi.test(myDog.name), 'message: Update myDog
's \"name\"
property to equal \"Happy Coder\".');",
- "assert(/\"name\": \"Coder\"/.test(code), 'message: Do not edit the myDog
definition');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Actualiza las propiedades de un objeto en JavaScript",
- "description": [
- "Después de que hayas creado un objeto de JavaScript, puedes actualizar sus propiedades en cualquier momento, tal y como harías con cualquier otra variable.",
- "Por ejemplo, echemos un vistazo a ourDog
:",
- "var ourDog = {
",
- " \"name\": \"Camper\",
",
- " \"legs\": 4,
",
- " \"tails\": 1,
",
- " \"friends\": [\"everything!\"]
",
- "};
",
- "Dado que es un perro particularmente feliz, vamos a cambiar su nombre a \"Happy Camper\". Así es como actualizamos la propiedad nombre del objeto: ",
- "ourDog.name = \"Happy Camper\";
",
- "Ahora, cuando ejecutemos return ourDog.name
, en lugar de obtener \"Camper\", vamos a recibir su nuevo nombre, \"Happy Camper\".",
- "Instrucciones
",
- "Vamos a actualizar la propiedad del objeto mydog
. Cambiemos su nombre de \"Coder\" a \"Happy Coder\"."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392d2",
- "title": "Add New Properties to a JavaScript Object",
- "description": [
- "You can add new properties to existing JavaScript objects the same way you would modify them.",
- "Here's how we would add a \"bark\"
property to ourDog
:",
- "ourDog.bark = \"bow-wow\";
",
- "or",
- "ourDog[\"bark\"] = \"bow-wow\";
",
- "Now when we evaluate ourDog.bark
, we'll get his bark, \"bow-wow\".",
- "
",
- "Add a \"bark\"
property to myDog
and set it to a dog sound, such as \"woof\". You may use either dot or bracket notation."
- ],
- "challengeSeed": [
- "// Example",
- "var ourDog = {",
- " \"name\": \"Camper\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"everything!\"]",
- "};",
- "",
- "ourDog.bark = \"bow-wow\";",
- "",
- "// Setup",
- "var myDog = {",
- " \"name\": \"Happy Coder\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"freeCodeCamp Campers\"]",
- "};",
- "",
- "// Only change code below this line.",
- ""
- ],
- "tail": [
- "(function(z){return z;})(myDog);"
- ],
- "solutions": [
- "var myDog = {\n \"name\": \"Happy Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"]\n};\nmyDog.bark = \"Woof Woof\";"
- ],
- "tests": [
- "assert(myDog.bark !== undefined, 'message: Add the property \"bark\"
to myDog
.');",
- "assert(!/bark[^\\n]:/.test(code), 'message: Do not add \"bark\"
to the setup section');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Añade nuevas propiedades a un objeto JavaScript",
- "description": [
- "Puedes añadir nuevas propiedades a objetos existente de la misma forma que usarías para modificarlos.",
- "Así es como añadimos una propiedad \"bark\"
(ladra) a nuestro objeto ourDog
:",
- "ourDog.bark = \"bow-wow\";
",
- "Ahora, cuando ejecutemos return ourDog.bark
, vamos a recbir su ladrido, \" bow-wow \".",
- "Instrucciones
",
- "Vamos a añadir una propiedad ladra
a myDog
y a ponerle un sonido de perro, tal como \"woof\"."
- ]
- }
- }
- },
- {
- "id": "56bbb991ad1ed5201cd392d3",
- "title": "Delete Properties from a JavaScript Object",
- "description": [
- "We can also delete properties from objects like this:",
- "delete ourDog.bark;
",
- "
",
- "Delete the \"tails\"
property from myDog
. You may use either dot or bracket notation."
- ],
- "challengeSeed": [
- "// Example",
- "var ourDog = {",
- " \"name\": \"Camper\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"everything!\"],",
- " \"bark\": \"bow-wow\"",
- "};",
- "",
- "delete ourDog.bark;",
- "",
- "// Setup",
- "var myDog = {",
- " \"name\": \"Happy Coder\",",
- " \"legs\": 4,",
- " \"tails\": 1,",
- " \"friends\": [\"freeCodeCamp Campers\"],",
- " \"bark\": \"woof\"",
- "};",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "(function(z){return z;})(myDog);"
- ],
- "solutions": [
- "var ourDog = {\n \"name\": \"Camper\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"everything!\"],\n \"bark\": \"bow-wow\"\n};\nvar myDog = {\n \"name\": \"Happy Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"],\n \"bark\": \"woof\"\n};\ndelete myDog.tails;"
- ],
- "tests": [
- "assert(typeof myDog === \"object\" && myDog.tails === undefined, 'message: Delete the property \"tails\"
from myDog
.');",
- "assert(code.match(/\"tails\": 1/g).length > 1, 'message: Do not modify the myDog
setup');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Elimina propiedades de un objeto JavaScript",
- "description": [
- "También podemos eliminar propiedades de los objetos de esta manera:",
- "delete ourDog.bark;
",
- "Instrucciones
",
- "Borremos la propiedad \"tails\"
de myDog
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244ca",
- "title": "Using Objects for Lookups",
- "description": [
- "Objects can be thought of as a key/value storage, like a dictionary. If you have tabular data, you can use an object to \"lookup\" values rather than a switch
statement or an if/else
chain. This is most useful when you know that your input data is limited to a certain range.",
- "Here is an example of a simple reverse alphabet lookup:",
- "var alpha = {
",
- "
1:\"Z\",
2:\"Y\",
3:\"X\",
4:\"W\",
...
24:\"C\",
25:\"B\",
26:\"A\"
};
alpha[2]; // \"Y\"
alpha[24]; // \"C\"
var value = 2;
alpha[value]; // \"Y\"
",
- "Convert the switch statement into an object called lookup
. Use it to look up val
and assign the associated string to the result
variable."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "function phoneticLookup(val) {",
- " var result = \"\";",
- "",
- " // Only change code below this line",
- " switch(val) {",
- " case \"alpha\": ",
- " result = \"Adams\";",
- " break;",
- " case \"bravo\": ",
- " result = \"Boston\";",
- " break;",
- " case \"charlie\": ",
- " result = \"Chicago\";",
- " break;",
- " case \"delta\": ",
- " result = \"Denver\";",
- " break;",
- " case \"echo\": ",
- " result = \"Easy\";",
- " break;",
- " case \"foxtrot\": ",
- " result = \"Frank\";",
- " }",
- "",
- " // Only change code above this line",
- " return result;",
- "}",
- "",
- "// Change this value to test",
- "phoneticLookup(\"charlie\");"
- ],
- "solutions": [
- "function phoneticLookup(val) {\n var result = \"\";\n\n var lookup = {\n alpha: \"Adams\",\n bravo: \"Boston\",\n charlie: \"Chicago\",\n delta: \"Denver\",\n echo: \"Easy\",\n foxtrot: \"Frank\"\n };\n\n result = lookup[val];\n\n return result;\n}"
- ],
- "tests": [
- "assert(phoneticLookup(\"alpha\") === 'Adams', 'message: phoneticLookup(\"alpha\")
should equal \"Adams\"
');",
- "assert(phoneticLookup(\"bravo\") === 'Boston', 'message: phoneticLookup(\"bravo\")
should equal \"Boston\"
');",
- "assert(phoneticLookup(\"charlie\") === 'Chicago', 'message: phoneticLookup(\"charlie\")
should equal \"Chicago\"
');",
- "assert(phoneticLookup(\"delta\") === 'Denver', 'message: phoneticLookup(\"delta\")
should equal \"Denver\"
');",
- "assert(phoneticLookup(\"echo\") === 'Easy', 'message: phoneticLookup(\"echo\")
should equal \"Easy\"
');",
- "assert(phoneticLookup(\"foxtrot\") === 'Frank', 'message: phoneticLookup(\"foxtrot\")
should equal \"Frank\"
');",
- "assert(typeof phoneticLookup(\"\") === 'undefined', 'message: phoneticLookup(\"\")
should equal undefined
');",
- "assert(code.match(/return\\sresult;/), 'message: You should not modify the return
statement');",
- "assert(!/case|switch|if/g.test(code), 'message: You should not use case
, switch
, or if
statements'); "
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Usar objetos para búsquedas",
- "description": [
- "Los objetos pueden ser considerados como un almacenamiento llave/valor, como un diccionario. Si tienes datos tabulados, puedes almacenarlos en un objeto para después \"buscar\" valores, en lugar de emplear una sentencia switch
o una secuencia de if/else
. Esto es más útil cuando sabes que tus datos de entrada son limitados a un cierto rango.",
- "Aquí está un ejemplo de una simple búsqueda inversa de alfabeto:",
- "var alfa = {
",
- "
1:\"Z\",
2:\"Y\",
3:\"X\",
4:\"W\",
...
24:\"C\",
25:\"B\",
26:\"A\"
};
alfa[2]; // \"Y\"
alfa[24]; // \"C\"
var valor = 2;
alfa[valor]; // \"Y\"Instrucciones
",
- "Convierte la sentencia switch en una tabla de búsqueda llamada lookup
. Usala para buscar val
y asigna la cadena asociada a la variable result
."
- ]
- }
- }
- },
- {
- "id": "567af2437cbaa8c51670a16c",
- "title": "Testing Objects for Properties",
- "description": [
- "Sometimes it is useful to check if the property of a given object exists or not. We can use the .hasOwnProperty(propname)
method of objects to determine if that object has the given property name. .hasOwnProperty()
returns true
or false
if the property is found or not.",
- "Example",
- "var myObj = {
",
- "
top: \"hat\",
bottom: \"pants\"
};
myObj.hasOwnProperty(\"top\"); // true
myObj.hasOwnProperty(\"middle\"); // false
",
- "Modify the function checkObj
to test myObj
for checkProp
. If the property is found, return that property's value. If not, return \"Not Found\"
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var myObj = {",
- " gift: \"pony\",",
- " pet: \"kitten\",",
- " bed: \"sleigh\"",
- "};",
- "",
- "function checkObj(checkProp) {",
- " // Your Code Here",
- " ",
- " return \"Change Me!\";",
- "}",
- "",
- "// Test your code by modifying these values",
- "checkObj(\"gift\");"
- ],
- "tail": [
- ""
- ],
- "solutions": [
- "var myObj = {\n gift: \"pony\",\n pet: \"kitten\",\n bed: \"sleigh\"\n};\nfunction checkObj(checkProp) {\n if(myObj.hasOwnProperty(checkProp)) {\n return myObj[checkProp];\n } else {\n return \"Not Found\";\n }\n}"
- ],
- "tests": [
- "assert(checkObj(\"gift\") === \"pony\", 'message: checkObj(\"gift\")
should return \"pony\"
.');",
- "assert(checkObj(\"pet\") === \"kitten\", 'message: checkObj(\"pet\")
should return \"kitten\"
.');",
- "assert(checkObj(\"house\") === \"Not Found\", 'message: checkObj(\"house\")
should return \"Not Found\"
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Probar si un objeto tiene cierta propiedad",
- "description": [
- "A veces es útil revisar si cierta propiedad existe o no en un objeto dado. Podemos usar el método de objetos .hasOwnProperty(nomprop)
para determinar si un objeto tiene la propiedad nomprop
. .hasOwnProperty()
retorna true
o false
si la propiedad es encontrada o no.",
- "Ejemplo",
- "var miObj = {
",
- "
arriba: \"sombrero\",
abajo: \"pantalones\"
};
miObj.hasOwnProperty(\"arriba\"); // true
miObj.hasOwnProperty(\"medio\"); // falseInstrucciones
",
- "Modifica la función checkObj
que prueba si myObj
tiene la propiedad checkProp
. Si la propiedad es encontrada, retorna el valor de esa propiedad. Si no, retorna \"Not Found\"
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244cb",
- "title": "Manipulating Complex Objects",
- "description": [
- "Sometimes you may want to store data in a flexible Data Structure. A JavaScript object is one way to handle flexible data. They allow for arbitrary combinations of strings, numbers, booleans, arrays, functions, and objects.",
- "Here's an example of a complex data structure:",
- "var ourMusic = [
",
- "This is an array which contains one object inside. The object has various pieces of metadata about an album. It also has a nested
{
\"artist\": \"Daft Punk\",
\"title\": \"Homework\",
\"release_year\": 1997,
\"formats\": [
\"CD\",
\"Cassette\",
\"LP\"
],
\"gold\": true
}
];\"formats\"
array. If you want to add more album records, you can do this by adding records to the top level array.",
- "Objects hold data in a property, which has a key-value format. In the example above, \"artist\": \"Daft Punk\"
is a property that has a key of \"artist\"
and a value of \"Daft Punk\"
.",
- "JavaScript Object Notation or JSON
is a related data interchange format used to store data.",
- "{
",
- "Note
\"artist\": \"Daft Punk\",
\"title\": \"Homework\",
\"release_year\": 1997,
\"formats\": [
\"CD\",
\"Cassette\",
\"LP\"
],
\"gold\": true
}
You will need to place a comma after every object in the array, unless it is the last object in the array.",
- "
",
- "Add a new album to the myMusic
array. Add artist
and title
strings, release_year
number, and a formats
array of strings."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "var myMusic = [",
- " {",
- " \"artist\": \"Billy Joel\",",
- " \"title\": \"Piano Man\",",
- " \"release_year\": 1973,",
- " \"formats\": [ ",
- " \"CD\",",
- " \"8T\",",
- " \"LP\"",
- " ],",
- " \"gold\": true",
- " }",
- " // Add record here",
- "];",
- ""
- ],
- "tail": [
- "(function(x){ if (Array.isArray(x)) { return JSON.stringify(x); } return \"myMusic is not an array\"})(myMusic);"
- ],
- "solutions": [
- "var myMusic = [\n {\n \"artist\": \"Billy Joel\",\n \"title\": \"Piano Man\",\n \"release_year\": 1973,\n \"formats\": [ \n \"CS\", \n \"8T\", \n \"LP\" ],\n \"gold\": true\n }, \n {\n \"artist\": \"ABBA\",\n \"title\": \"Ring Ring\",\n \"release_year\": 1973,\n \"formats\": [ \n \"CS\", \n \"8T\", \n \"LP\",\n \"CD\",\n ]\n }\n];"
- ],
- "tests": [
- "assert(Array.isArray(myMusic), 'message: myMusic
should be an array');",
- "assert(myMusic.length > 1, 'message: myMusic
should have at least two elements');",
- "assert(typeof myMusic[1] === 'object', 'message: myMusic[1]
should be an object');",
- "assert(Object.keys(myMusic[1]).length > 3, 'message: myMusic[1]
should have at least 4 properties');",
- "assert(myMusic[1].hasOwnProperty('artist') && typeof myMusic[1].artist === 'string', 'message: myMusic[1]
should contain an artist
property which is a string');",
- "assert(myMusic[1].hasOwnProperty('title') && typeof myMusic[1].title === 'string', 'message: myMusic[1]
should contain a title
property which is a string');",
- "assert(myMusic[1].hasOwnProperty('release_year') && typeof myMusic[1].release_year === 'number', 'message: myMusic[1]
should contain a release_year
property which is a number');",
- "assert(myMusic[1].hasOwnProperty('formats') && Array.isArray(myMusic[1].formats), 'message: myMusic[1]
should contain a formats
property which is an array');",
- "assert(myMusic[1].formats.every(function(item) { return (typeof item === \"string\")}) && myMusic[1].formats.length > 1, 'message: formats
should be an array of strings with at least two elements');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Manipula objetos complicados",
- "description": [
- "Los objetos JavaScript son flexibles porque permiten Estructuras de Datos con combinaciones arbitrarias de cadenas, números, booleanos, vectores, funciones, y objetos.",
- "Aquí está un ejemplo de un objeto complicado:",
- "var nuestraMusica = [
",
- "Este es un vector de objetos con diversos metadatos acerca de un álbum musical. Además tiene anidado un vector
{
\"artista\": \"Daft Punk\",
\"titulo\": \"Homework\",
\"año_publicacion\": 1997,
\"formatos\": [
\"CD\",
\"Cassette\",
\"LP\" ],
\"oro\": true
}
];formatos
. En el vector de nivel superior, pueden añadirse otros registros del álbum.",
- "Nota
En vectores que tengan más de un objeto, necesitarás separar un objeto de otro mediante comas.",
- "Instrucciones
",
- "Agrega un nuevo álbum al objeto myMusic
. Agrega las cadenas artist
y title
, el número release_year
y un vector de cadenas formats
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244cc",
- "title": "Accessing Nested Objects",
- "description": [
- "The sub-properties of objects can be accessed by chaining together the dot or bracket notation.",
- "Here is a nested object:",
- "var ourStorage = {
",
- "
\"desk\": {
\"drawer\": \"stapler\"
},
\"cabinet\": {
\"top drawer\": {
\"folder1\": \"a file\",
\"folder2\": \"secrets\"
},
\"bottom drawer\": \"soda\"
}
};
ourStorage.cabinet[\"top drawer\"].folder2; // \"secrets\"
ourStorage.desk.drawer; // \"stapler\"
",
- "Access the myStorage
object and assign the contents of the glove box
property to the gloveBoxContents
variable. Use bracket notation for properties with a space in their name."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var myStorage = {",
- " \"car\": {",
- " \"inside\": {",
- " \"glove box\": \"maps\",",
- " \"passenger seat\": \"crumbs\"",
- " },",
- " \"outside\": {",
- " \"trunk\": \"jack\"",
- " }",
- " }",
- "};",
- "",
- "var gloveBoxContents = undefined; // Change this line",
- ""
- ],
- "tail": [
- "(function(x) { ",
- " if(typeof x != 'undefined') { ",
- " return \"gloveBoxContents = \" + x;",
- " }",
- " return \"gloveBoxContents is undefined\";",
- "})(gloveBoxContents);"
- ],
- "solutions": [
- "var myStorage = { \n \"car\":{ \n \"inside\":{ \n \"glove box\":\"maps\",\n \"passenger seat\":\"crumbs\"\n },\n \"outside\":{ \n \"trunk\":\"jack\"\n }\n }\n};\nvar gloveBoxContents = myStorage.car.inside[\"glove box\"];"
- ],
- "tests": [
- "assert(gloveBoxContents === \"maps\", 'message: gloveBoxContents
should equal \"maps\"');",
- "assert(/=\\s*myStorage\\.car\\.inside\\[\\s*(\"|')glove box\\1\\s*\\]/g.test(code), 'message: Use dot and bracket notation to access myStorage
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a objetos anidados",
- "description": [
- "Las sub-propiedades de los objetos pueden ser accesadas mediante encadenamiento de la notación punto o corchete.",
- "Aquí está un objeto anidado:",
- "var nuestroAlmacen = {
",
- "
\"escritorio\": {
\"cajon\": \"grapadora\"
},
\"armario\": {
\"cajón superior\": {
\"legajador1\": \"un archivo\",
\"legajador2\": \"secretos\"
},
\"cajón inferior\": \"gaseosa\"
}
}
nuestroAlmacen.armario[\"cajón superior\"].legajador2; // \"secretos\"
nuestroAlmacen.escritorio.cajon; // \"grapadora\"Instrucciones
",
- "Accede al objeto myStorage
para recuperar el contenido de glove box
. Usa notación corchete para las propiedades con un espacio en su nombre."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/accessing-nested-objects-in-json"
- },
- {
- "id": "56533eb9ac21ba0edf2244cd",
- "title": "Accessing Nested Arrays",
- "description": [
- "As we have seen in earlier examples, objects can contain both nested objects and nested arrays. Similar to accessing nested objects, Array bracket notation can be chained to access nested arrays.",
- "Here is an example of how to access a nested array:",
- "var ourPets = [
",
- "
{
animalType: \"cat\",
names: [
\"Meowzer\",
\"Fluffy\",
\"Kit-Cat\"
]
},
{
animalType: \"dog\",
names: [
\"Spot\",
\"Bowser\",
\"Frankie\"
]
}
];
ourPets[0].names[1]; // \"Fluffy\"
ourPets[1].names[0]; // \"Spot\"
",
- "Retrieve the second tree from the variable myPlants
using object dot and array bracket notation."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var myPlants = [",
- " { ",
- " type: \"flowers\",",
- " list: [",
- " \"rose\",",
- " \"tulip\",",
- " \"dandelion\"",
- " ]",
- " },",
- " {",
- " type: \"trees\",",
- " list: [",
- " \"fir\",",
- " \"pine\",",
- " \"birch\"",
- " ]",
- " } ",
- "];",
- "",
- "// Only change code below this line",
- "",
- "var secondTree = \"\"; // Change this line",
- ""
- ],
- "tail": [
- "(function(x) { ",
- " if(typeof x != 'undefined') { ",
- " return \"secondTree = \" + x;",
- " }",
- " return \"secondTree is undefined\";",
- "})(secondTree);"
- ],
- "solutions": [
- "var myPlants = [\n { \n type: \"flowers\",\n list: [\n \"rose\",\n \"tulip\",\n \"dandelion\"\n ]\n },\n {\n type: \"trees\",\n list: [\n \"fir\",\n \"pine\",\n \"birch\"\n ]\n } \n];\n\n// Only change code below this line\n\nvar secondTree = myPlants[1].list[1];"
- ],
- "tests": [
- "assert(secondTree === \"pine\", 'message: secondTree
should equal \"pine\"');",
- "assert(/=\\s*myPlants\\[1\\].list\\[1\\]/.test(code), 'message: Use dot and bracket notation to access myPlants
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Acceder a vectores anidados",
- "description": [
- "Como hemos visto en ejemplos anteriores, los objetos pueden contener objetos anidados y vectores anidados. De forma similar a acceder a objetos anidados, la notación corchete en vectores puede ser encadenada para acceder a vectores anidados.",
- "Aquí está un ejemplo de como acceder a un vector anidado:",
- "var nuestrasMascotas = {
",
- "
\"gatos\": [
\"Maullador\",
\"Blandito\",
\"Kit-Cat\"
],
\"perros\": [
\"Mancha\",
\"Bowser\",
\"Frankie\"
]
};
nuestrasMascotas.cats[1]; // \"Blandito\"
nuestrasMascotas.dogs[0]; // \"Mancha\"Instrucciones
",
- "Recupera el segundo arbol de la variable myPlants
usando notación punto para objetos y notación corchete para vectores."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/access-array-data-with-indexes"
- },
- {
- "id": "56533eb9ac21ba0edf2244cf",
- "title": "Record Collection",
- "description": [
- "You are given a JSON object representing a part of your musical album collection. Each album has several properties and a unique id number as its key. Not all albums have complete information.",
- "Write a function which takes an album's id
(like 2548
), a property prop
(like \"artist\"
or \"tracks\"
), and a value
(like \"Addicted to Love\"
) to modify the data in this collection.",
- "If prop
isn't \"tracks\"
and value
isn't empty (\"\"
), update or set the value
for that record album's property.",
- "Your function must always return the entire collection object.",
- "There are several rules for handling incomplete data:",
- "If prop
is \"tracks\"
but the album doesn't have a \"tracks\"
property, create an empty array before adding the new value to the album's corresponding property.",
- "If prop
is \"tracks\"
and value
isn't empty (\"\"
), push the value
onto the end of the album's existing tracks
array.",
- "If value
is empty (\"\"
), delete the given prop
property from the album.",
- "Hints
Use bracket notation
when accessing object properties with variables.",
- "Push is an array method you can read about on Mozilla Developer Network.",
- "You may refer back to Manipulating Complex Objects Introducing JavaScript Object Notation (JSON) for a refresher."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Setup",
- "var collection = {",
- " \"2548\": {",
- " \"album\": \"Slippery When Wet\",",
- " \"artist\": \"Bon Jovi\",",
- " \"tracks\": [ ",
- " \"Let It Rock\", ",
- " \"You Give Love a Bad Name\" ",
- " ]",
- " },",
- " \"2468\": {",
- " \"album\": \"1999\",",
- " \"artist\": \"Prince\",",
- " \"tracks\": [ ",
- " \"1999\", ",
- " \"Little Red Corvette\" ",
- " ]",
- " },",
- " \"1245\": {",
- " \"artist\": \"Robert Palmer\",",
- " \"tracks\": [ ]",
- " },",
- " \"5439\": {",
- " \"album\": \"ABBA Gold\"",
- " }",
- "};",
- "// Keep a copy of the collection for tests",
- "var collectionCopy = JSON.parse(JSON.stringify(collection));",
- "",
- "// Only change code below this line",
- "function updateRecords(id, prop, value) {",
- " ",
- " ",
- " return collection;",
- "}",
- "",
- "// Alter values below to test your code",
- "updateRecords(5439, \"artist\", \"ABBA\");",
- ""
- ],
- "tail": [
- ";(function(x) { return \"collection = \\n\" + JSON.stringify(x, '\\n', 2); })(collection);"
- ],
- "solutions": [
- "var collection = {\n 2548: {\n album: \"Slippery When Wet\",\n artist: \"Bon Jovi\",\n tracks: [ \n \"Let It Rock\", \n \"You Give Love a Bad Name\" \n ]\n },\n 2468: {\n album: \"1999\",\n artist: \"Prince\",\n tracks: [ \n \"1999\", \n \"Little Red Corvette\" \n ]\n },\n 1245: {\n artist: \"Robert Palmer\",\n tracks: [ ]\n },\n 5439: {\n album: \"ABBA Gold\"\n }\n};\n// Keep a copy of the collection for tests\nvar collectionCopy = JSON.parse(JSON.stringify(collection));\n\n// Only change code below this line\nfunction updateRecords(id, prop, value) {\n if(value === \"\") delete collection[id][prop];\n else if(prop === \"tracks\") {\n collection[id][prop] = collection[id][prop] || [];\n collection[id][prop].push(value);\n } else {\n collection[id][prop] = value;\n }\n \n return collection;\n}"
- ],
- "tests": [
- "collection = collectionCopy; assert(updateRecords(5439, \"artist\", \"ABBA\")[5439][\"artist\"] === \"ABBA\", 'message: After updateRecords(5439, \"artist\", \"ABBA\")
, artist
should be \"ABBA\"
');",
- "assert(updateRecords(5439, \"tracks\", \"Take a Chance on Me\")[5439][\"tracks\"].pop() === \"Take a Chance on Me\", 'message: After updateRecords(5439, \"tracks\", \"Take a Chance on Me\")
, tracks
should have \"Take a Chance on Me\"
as the last element.');",
- "updateRecords(2548, \"artist\", \"\"); assert(!collection[2548].hasOwnProperty(\"artist\"), 'message: After updateRecords(2548, \"artist\", \"\")
, artist
should not be set');",
- "assert(updateRecords(1245, \"tracks\", \"Addicted to Love\")[1245][\"tracks\"].pop() === \"Addicted to Love\", 'message: After updateRecords(1245, \"tracks\", \"Addicted to Love\")
, tracks
should have \"Addicted to Love\"
as the last element.');",
- "assert(updateRecords(2468, \"tracks\", \"Free\")[2468][\"tracks\"][0] === \"1999\", 'message: After updateRecords(2468, \"tracks\", \"Free\")
, tracks
should have \"1999\"
as the first element.');",
- "updateRecords(2548, \"tracks\", \"\"); assert(!collection[2548].hasOwnProperty(\"tracks\"), 'message: After updateRecords(2548, \"tracks\", \"\")
, tracks
should not be set');",
- "assert(updateRecords(1245, \"album\", \"Riptide\")[1245][\"album\"] === \"Riptide\", 'message: After updateRecords(1245, \"album\", \"Riptide\")
, album
should be \"Riptide\"
');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Colección de registros",
- "description": [
- "Se te da un objeto que representa (una pequeña parte de) tu colección de grabaciones. Cada álbum es identificado por un número id único y tiene varias propiedades. No todos los álbumes tienen la información completa.",
- "Escribe una función que reciba un id
, una propiedad (prop
) y un valor (value
).",
- "Para el id
dado, en la colección collection
:",
- "Si el valor value
no está en blanco (value !== \"\"
) y prop
no es \"tracks\"
entonces actualiza o establece el valor de la propiedad prop
.",
- "Si la propiedad prop
es \"tracks\"
y value
no está en blanco, empuja (push) el valor value
al final del vector tracks
.",
- "Si el valor value
está en blanco, elimina esa prop
.",
- "Siempre retorna el objeto collection
entero.",
- "Nota
No olvides usar notación corchete
cuando accedes a propiedades de objetos con variables."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb1bdef",
- "title": "Iterate with JavaScript While Loops",
- "description": [
- "You can run the same code multiple times by using a loop.",
- "The first type of loop we will learn is called a \"while
\" loop because it runs \"while\" a specified condition is true and stops once that condition is no longer true.",
- "var ourArray = [];
",
- "Let's try getting a while loop to work by pushing values to an array.",
- "
var i = 0;
while(i < 5) {
ourArray.push(i);
i++;
}
",
- "Push the numbers 0 through 4 to myArray
using a while
loop."
- ],
- "challengeSeed": [
- "// Setup",
- "var myArray = [];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var myArray = [];\nvar i = 0;\nwhile(i < 5) {\n myArray.push(i);\n i++;\n}"
- ],
- "tests": [
- "assert(code.match(/while/g), 'message: You should be using a while
loop for this.');",
- "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray
should equal [0,1,2,3,4]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Iterar con JavaScript con ciclos while",
- "description": [
- "Puede ejecutar el mismo código varias veces mediante el uso de un ciclo.",
- "Otro tipo de ciclo de JavaScript se llama un ciclo \"while\", ya que se ejecuta, \"mientras que\" algo sea cierto y se detiene una vez que ya no sea así.",
- "var ourArray = [];
",
- "var i = 0;
",
- "while(i < 5) {
",
- " ourArray.push(i);
",
- " i++;
",
- "}
",
- "Intentemos que un ciclo while
empuje valores en un vector.",
- "Instrucciones
",
- "Empuja los números de 0 a 4 para myArray
utilizando un ciclo while
."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb5bdef",
- "title": "Iterate with JavaScript For Loops",
- "description": [
- "You can run the same code multiple times by using a loop.",
- "The most common type of JavaScript loop is called a \"for loop
\" because it runs \"for\" a specific number of times.",
- "For loops are declared with three optional expressions separated by semicolons:",
- "for ([initialization]; [condition]; [final-expression])
",
- "The initialization
statement is executed one time only before the loop starts. It is typically used to define and setup your loop variable.",
- "The condition
statement is evaluated at the beginning of every loop iteration and will continue as long as it evaluates to true
. When condition
is false
at the start of the iteration, the loop will stop executing. This means if condition
starts as false
, your loop will never execute.",
- "The final-expression
is executed at the end of each loop iteration, prior to the next condition
check and is usually used to increment or decrement your loop counter.",
- "In the following example we initialize with i = 0
and iterate while our condition i < 5
is true. We'll increment i
by 1
in each loop iteration with i++
as our final-expression
.",
- "var ourArray = [];
",
- "
for (var i = 0; i < 5; i++) {
ourArray.push(i);
}ourArray
will now contain [0,1,2,3,4]
.",
- "
",
- "Use a for
loop to work to push the values 1 through 5 onto myArray
."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [];",
- "",
- "for (var i = 0; i < 5; i++) {",
- " ourArray.push(i);",
- "}",
- "",
- "// Setup",
- "var myArray = [];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "if (typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var ourArray = [];\nfor (var i = 0; i < 5; i++) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 1; i < 6; i++) {\n myArray.push(i);\n}"
- ],
- "tests": [
- "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
- "assert.deepEqual(myArray, [1,2,3,4,5], 'message: myArray
should equal [1,2,3,4,5]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Iterar en JavaScript con ciclos for",
- "description": [
- "Puede ejecutar el mismo código varias veces mediante el uso de un ciclo.",
- "El tipo más común de bucle de JavaScript se llama \"ciclo for\"porque se ejecuta \"por\" (for) un número específico de veces.",
- "Los ciclos for se declaran con tres expresiones opcionales separadas por punto y coma:",
- "for ([inicialización]; [condición]; [expresión-final])
",
- "La inicialización
se ejecuta sólo una vez antes de que empiece el ciclo. Normalmente se utiliza para definir e inicializar su variable de ciclo. ",
- "La expresión condición
se evalúa al principio de cada iteración del ciclo y continuará en el ciclo siempre y cuando sea verdadera (true
). Cuando la condición
sea falsa (false
) al comienzo de la iteración, se detendrá la ejecución del ciclo. Esto significa que si la condición
inicia en el valor falso false
, el ciclo no se ejecutará. ",
- "La expresión final
se ejecuta al final de cada repetición del ciclo, antes del siguiente chequeo de la condición
y se utiliza generalmente para aumentar o disminuir el contador del ciclo.",
- "En el siguiente ejemplo inicializamos con i = 0
e iteramos mientras nuestra condición i <5
sea verdadera. Vamos a incrementar i
en 1
en cada iteración del ciclo con i++
como nuestra expresión final
. ",
- "var ourArray = [];
",
- "for (var i = 0; i < 5; i++) {
",
- " ourArray.push(i);
",
- "}
",
- "ourArray
ahora contendrá [0,1,2,3,4]
.",
- "Instrucciones
",
- "Vamos a utilizar un ciclo for
para empujar los valores del 1 al 5 en myArray
."
- ]
- }
- }
- },
- {
- "id": "56104e9e514f539506016a5c",
- "title": "Iterate Odd Numbers With a For Loop",
- "description": [
- "For loops don't have to iterate one at a time. By changing our final-expression
, we can count by even numbers.",
- "We'll start at i = 0
and loop while i < 10
. We'll increment i
by 2 each loop with i += 2
.",
- "var ourArray = [];
",
- "
for (var i = 0; i < 10; i += 2) {
ourArray.push(i);
}ourArray
will now contain [0,2,4,6,8]
.",
- "Let's change our initialization
so we can count by odd numbers.",
- "
",
- "Push the odd numbers from 1 through 9 to myArray
using a for
loop."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [];",
- "",
- "for (var i = 0; i < 10; i += 2) {",
- " ourArray.push(i);",
- "}",
- "",
- "// Setup",
- "var myArray = [];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var ourArray = [];\nfor (var i = 0; i < 10; i += 2) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 1; i < 10; i += 2) {\n myArray.push(i);\n}"
- ],
- "tests": [
- "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
- "assert.deepEqual(myArray, [1,3,5,7,9], 'message: myArray
should equal [1,3,5,7,9]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Itera por los números pares con un ciclo for",
- "description": [
- "Los ciclos for
no siempre iteran incrementado de a uno. Cambiando nuestra expresión final
, podemos contar los números pares.",
- "Vamos a empezar con i = 0
e iterar mientras i <10
. Vamos a incrementar i
de a 2 en cada iteración i + = 2
. ",
- "var ourArray = [];
",
- "for (var i = 0; i < 10; i += 2) {
",
- " ourArray.push(i);
",
- "}
",
- "ourArray
ahora contendrá [0,2,4,6,8]
.",
- "Vamos a cambiar nuestra inicialización
y expresión final
para que podamos contar los números impares.",
- "Instrucciones
",
- "Empuja los números impares del 1 al 9 en myArray
utilizando un ciclo for
."
- ]
- }
- }
- },
- {
- "id": "56105e7b514f539506016a5e",
- "title": "Count Backwards With a For Loop",
- "description": [
- "A for loop can also count backwards, so long as we can define the right conditions.",
- "In order to count backwards by twos, we'll need to change our initialization
, condition
, and final-expression
.",
- "We'll start at i = 10
and loop while i > 0
. We'll decrement i
by 2 each loop with i -= 2
.",
- "var ourArray = [];
",
- "
for (var i=10; i > 0; i-=2) {
ourArray.push(i);
}ourArray
will now contain [10,8,6,4,2]
.",
- "Let's change our initialization
and final-expression
so we can count backward by twos by odd numbers.",
- "
",
- "Push the odd numbers from 9 through 1 to myArray
using a for
loop."
- ],
- "challengeSeed": [
- "// Example",
- "var ourArray = [];",
- "",
- "for (var i = 10; i > 0; i -= 2) {",
- " ourArray.push(i);",
- "}",
- "",
- "// Setup",
- "var myArray = [];",
- "",
- "// Only change code below this line.",
- "",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var ourArray = [];\nfor (var i = 10; i > 0; i -= 2) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 9; i > 0; i -= 2) {\n myArray.push(i);\n}"
- ],
- "tests": [
- "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for
loop for this.');",
- "assert(code.match(/myArray.push/), 'message: You should be using the array method push
.');",
- "assert.deepEqual(myArray, [9,7,5,3,1], 'message: myArray
should equal [9,7,5,3,1]
.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Cuenta hacia atrás con un ciclo for",
- "description": [
- "Un ciclo también puede contar hacia atrás, siempre y cuando definamos las condiciones adecuadas.",
- "Para contar hacia atrás de dos en dos, tendremos que cambiar nuestra inicialización
, la condición
y la última-expresión
.",
- "Vamos a empezar con i = 10
e iteraremos mientras i > 0
. Vamos a decrementar i
de a 2 por cada iteración con i -= 2
. ",
- "var ourArray = [];
",
- "for (var i = 10; i > 0; i -= 2) {
",
- " ourArray.push(i);
",
- "}
",
- "ourArray
ahora contendrá [10,8,6,4,2]
.",
- "Vamos a cambiar nuestra inicialización
y la expresión final
para que podamos contar hacia atrás de dos en dos pero números impares.",
- "Instrucciones
",
- "Empuja los números impares del 9 a 1 en myArray
utilizando un ciclo for
."
- ]
- }
- }
- },
- {
- "id": "5675e877dbd60be8ad28edc6",
- "title": "Iterate Through an Array with a For Loop",
- "description": [
- "A common task in JavaScript is to iterate through the contents of an array. One way to do that is with a for
loop. This code will output each element of the array arr
to the console:",
- "var arr = [10,9,8,7,6];
",
- "Remember that Arrays have zero-based numbering, which means the last index of the array is length - 1. Our condition for this loop is
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}i < arr.length
, which stops when i
is at length - 1.",
- "
",
- "Declare and initialize a variable total
to 0
. Use a for
loop to add the value of each element of the myArr
array to total
."
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "// Example",
- "var ourArr = [ 9, 10, 11, 12];",
- "var ourTotal = 0;",
- "",
- "for (var i = 0; i < ourArr.length; i++) {",
- " ourTotal += ourArr[i];",
- "}",
- "",
- "// Setup",
- "var myArr = [ 2, 3, 4, 5, 6];",
- "",
- "// Only change code below this line",
- "",
- ""
- ],
- "tail": [
- "(function(){if(typeof total !== 'undefined') { return \"total = \" + total; } else { return \"total is undefined\";}})()"
- ],
- "solutions": [
- "var ourArr = [ 9, 10, 11, 12];\nvar ourTotal = 0;\n\nfor (var i = 0; i < ourArr.length; i++) {\n ourTotal += ourArr[i];\n}\n\nvar myArr = [ 2, 3, 4, 5, 6];\nvar total = 0;\n\nfor (var i = 0; i < myArr.length; i++) {\n total += myArr[i];\n}"
- ],
- "tests": [
- "assert(code.match(/var.*?total\\s*=\\s*0.*?;/), 'message: total
should be declared and initialized to 0');",
- "assert(total === 20, 'message: total
should equal 20');",
- "assert(code.match(/for\\s*\\(/g).length > 1 && code.match(/myArr\\s*\\[/), 'message: You should use a for
loop to iterate through myArr
');",
- "assert(!code.match(/total[\\s\\+\\-]*=\\s*(\\d(?!\\s*[;,])|[1-9])/g), 'message: Do not set total
to 20 directly');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Iterar a través de un vector con un ciclo for",
- "description": [
- "Una tarea común en JavaScript es iterar a traves del contenido de un vector. Una manera de hacerlo es con un ciclo for
. Este código imprimirá cada elemento del vector arr
en la consola:",
- "var arr = [10,9,8,7,6];
",
- "Recuerda que los vectores tienen numeración que comienza en cero, la cual significa que el último índice del vector es su longitud - 1. Nuestra condición para este ciclo es
for (var i=0; i < arr.length; i++) {
console.log(arr[i]);
}i < arr.length
, que lo detendrá cuando i
sea la longitud - 1.",
- "Instrucciones
",
- "Declara e inicializa una variable total
en 0
. Usa un ciclo for
para añadir el valor de cada elemento del vector myArr
a total
."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244e1",
- "title": "Nesting For Loops",
- "description": [
- "If you have a multi-dimensional array, you can use the same logic as the prior waypoint to loop through both the array and any sub-arrays. Here is an example:",
- "var arr = [
",
- "This outputs each sub-element in
[1,2], [3,4], [5,6]
];
for (var i=0; i < arr.length; i++) {
for (var j=0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}arr
one at a time. Note that for the inner loop, we are checking the .length
of arr[i]
, since arr[i]
is itself an array.",
- "
",
- "Modify function multiplyAll
so that it multiplies the product
variable by each number in the sub-arrays of arr
"
- ],
- "releasedOn": "January 1, 2016",
- "challengeSeed": [
- "function multiplyAll(arr) {",
- " var product = 1;",
- " // Only change code below this line",
- " ",
- " // Only change code above this line",
- " return product;",
- "}",
- "",
- "// Modify values below to test your code",
- "multiplyAll([[1,2],[3,4],[5,6,7]]);",
- ""
- ],
- "tail": [
- ""
- ],
- "solutions": [
- "function multiplyAll(arr) {\n var product = 1;\n for (var i = 0; i < arr.length; i++) {\n for (var j = 0; j < arr[i].length; j++) {\n product *= arr[i][j];\n }\n }\n return product;\n}\n\nmultiplyAll([[1,2],[3,4],[5,6,7]]);"
- ],
- "tests": [
- "assert(multiplyAll([[1],[2],[3]]) === 6, 'message: multiplyAll([[1],[2],[3]])
should return 6
');",
- "assert(multiplyAll([[1,2],[3,4],[5,6,7]]) === 5040, 'message: multiplyAll([[1,2],[3,4],[5,6,7]])
should return 5040
');",
- "assert(multiplyAll([[5,1],[0.2, 4, 0.5],[3, 9]]) === 54, 'message: multiplyAll([[5,1],[0.2, 4, 0.5],[3, 9]])
should return 54
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Anidar ciclos for",
- "description": [
- "Si tienes una matriz multi-dimensional, puedes usar la misma lógica del punto anterior para iterar a través de un vector y cualquier sub-vector. Aquí está un ejemplo:",
- "var arr = [
",
- "Esto imprime cada sub-elemento en
[1,2], [3,4], [5,6]
];
for (var i=0; i < arr.length; i++) {
for (var j=0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}arr
uno a la vez. Nota que en el ciclo interior, estamos comprobando la longitud .length
de arr[i]
, ya que arr[i]
es por si mismo un vector.",
- "Instrucciones
",
- "Modifica la función multiplyAll
de manera que esta multiplique la variable product
por cada número en los sub-vectores de arr
"
- ]
- }
- }
- },
- {
- "id": "5a2efd662fb457916e1fe604",
- "title": "Iterate with JavaScript Do...While Loops",
- "description": [
- "You can run the same code multiple times by using a loop.",
- "The next type of loop you will learn is called a \"do...while
\" loop because it first will \"do
\" one pass of the code inside the loop no matter what, and then it runs \"while
\" a specified condition is true and stops once that condition is no longer true. Let's look at an example.",
- "var ourArray = [];
",
- "This behaves just as you would expect with any other type of loop, and the resulting array will look like
var i = 0;
do {
ourArray.push(i);
i++;
} while (i < 5);[0, 1, 2, 3, 4]
. However, what makes the do...while
different from other loops is how it behaves when the condition fails on the first check. Let's see this in action.",
- "Here is a regular while loop that will run the code in the loop as long as i < 5
.",
- "var ourArray = [];
",
- "Notice that we initialize the value of
var i = 5;
while (i < 5) {
ourArray.push(i);
i++;
}i
to be 5. When we execute the next line, we notice that i
is not less than 5. So we do not execute the code inside the loop. The result is that ourArray
will end up with nothing added to it, so it will still look like this []
when all the code in the example above finishes running.",
- "Now, take a look at a do...while
loop.",
- "var ourArray = [];
",
- "In this case, we initialize the value of
var i = 5;
do {
ourArray.push(i);
i++;
} while (i < 5);i
as 5, just like we did with the while loop. When we get to the next line, there is no check for the value of i
, so we go to the code inside the curly braces and execute it. We will add one element to the array and increment i
before we get to the condition check. Then, when we get to checking if i < 5
see that i
is now 6, which fails the conditional check. So we exit the loop and are done. At the end of the above example, the value of ourArray
is [5]
.",
- "Essentially, a do...while
loop ensures that the code inside the loop will run at least once.",
- "Let's try getting a do...while
loop to work by pushing values to an array.",
- "
",
- "Change the while
loop in the code to a do...while
loop so that the loop will push the number 10 to myArray
, and i
will be equal to 11
when your code finishes running."
- ],
- "challengeSeed": [
- "// Setup",
- "var myArray = [];",
- "var i = 10;",
- "",
- "// Only change code below this line.",
- "",
- "while (i < 5) {",
- " myArray.push(i);",
- " i++;",
- "}",
- ""
- ],
- "tail": [
- "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}"
- ],
- "solutions": [
- "var myArray = [];\nvar i = 10;\ndo {\n myArray.push(i);\n i++;\n} while (i < 5)"
- ],
- "tests": [
- "assert(code.match(/do/g), 'message: You should be using a do...while
loop for this.');",
- "assert.deepEqual(myArray, [10], 'message: myArray
should equal [10]
.');",
- "assert.deepEqual(i, 11, 'message: i
should equal 11
');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- }
- },
- {
- "id": "5688e62ea601b2482ff8422b",
- "title": "Profile Lookup",
- "description": [
- "We have an array of objects representing different people in our contacts lists.",
- "A lookUpProfile
function that takes name
and a property (prop
) as arguments has been pre-written for you.",
- "The function should check if name
is an actual contact's firstName
and the given property (prop
) is a property of that contact.",
- "If both are true, then return the \"value\" of that property.",
- "If name
does not correspond to any contacts then return \"No such contact\"
",
- "If prop
does not correspond to any valid properties of a contact found to match name
then return \"No such property\"
"
- ],
- "releasedOn": "January 8, 2016",
- "challengeSeed": [
- "//Setup",
- "var contacts = [",
- " {",
- " \"firstName\": \"Akira\",",
- " \"lastName\": \"Laine\",",
- " \"number\": \"0543236543\",",
- " \"likes\": [\"Pizza\", \"Coding\", \"Brownie Points\"]",
- " },",
- " {",
- " \"firstName\": \"Harry\",",
- " \"lastName\": \"Potter\",",
- " \"number\": \"0994372684\",",
- " \"likes\": [\"Hogwarts\", \"Magic\", \"Hagrid\"]",
- " },",
- " {",
- " \"firstName\": \"Sherlock\",",
- " \"lastName\": \"Holmes\",",
- " \"number\": \"0487345643\",",
- " \"likes\": [\"Intriguing Cases\", \"Violin\"]",
- " },",
- " {",
- " \"firstName\": \"Kristian\",",
- " \"lastName\": \"Vos\",",
- " \"number\": \"unknown\",",
- " \"likes\": [\"JavaScript\", \"Gaming\", \"Foxes\"]",
- " }",
- "];",
- "",
- "",
- "function lookUpProfile(name, prop){",
- "// Only change code below this line",
- "",
- "// Only change code above this line",
- "}",
- "",
- "// Change these values to test your function",
- "lookUpProfile(\"Akira\", \"likes\");"
- ],
- "solutions": [
- "var contacts = [\n {\n \"firstName\": \"Akira\",\n \"lastName\": \"Laine\",\n \"number\": \"0543236543\",\n \"likes\": [\"Pizza\", \"Coding\", \"Brownie Points\"]\n },\n {\n \"firstName\": \"Harry\",\n \"lastName\": \"Potter\",\n \"number\": \"0994372684\",\n \"likes\": [\"Hogwarts\", \"Magic\", \"Hagrid\"]\n },\n {\n \"firstName\": \"Sherlock\",\n \"lastName\": \"Holmes\",\n \"number\": \"0487345643\",\n \"likes\": [\"Intriguing Cases\", \"Violin\"]\n },\n {\n \"firstName\": \"Kristian\",\n \"lastName\": \"Vos\",\n \"number\": \"unknown\",\n \"likes\": [\"JavaScript\", \"Gaming\", \"Foxes\"]\n },\n];\n\n\n//Write your function in between these comments\nfunction lookUpProfile(name, prop){\n for(var i in contacts){\n if(contacts[i].firstName === name) {\n return contacts[i][prop] || \"No such property\";\n }\n }\n return \"No such contact\";\n}\n//Write your function in between these comments\n\nlookUpProfile(\"Akira\", \"likes\");"
- ],
- "tests": [
- "assert(lookUpProfile('Kristian','lastName') === \"Vos\", 'message: \"Kristian\", \"lastName\"
should return \"Vos\"
');",
- "assert.deepEqual(lookUpProfile(\"Sherlock\", \"likes\"), [\"Intriguing Cases\", \"Violin\"], 'message: \"Sherlock\", \"likes\"
should return [\"Intriguing Cases\", \"Violin\"]
');",
- "assert(typeof lookUpProfile(\"Harry\", \"likes\") === \"object\", 'message: \"Harry\",\"likes\"
should return an array');",
- "assert(lookUpProfile(\"Bob\", \"number\") === \"No such contact\", 'message: \"Bob\", \"number\"
should return \"No such contact\"');",
- "assert(lookUpProfile(\"Bob\", \"potato\") === \"No such contact\", 'message: \"Bob\", \"potato\"
should return \"No such contact\"');",
- "assert(lookUpProfile(\"Akira\", \"address\") === \"No such property\", 'message: \"Akira\", \"address\"
should return \"No such property\"');"
- ],
- "type": "checkpoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Búsqueda de perfiles",
- "description": [
- "Tenemos un vector de objetos que representan diferentes personas en nuestra lista de contactos.",
- "Una función lookUp
que recibe el nombre (firstName
) y una propiedad (prop
) como argumentos ya ha sido escrita previamente para ti.",
- "La función debe comprobar si firstName
es un nombre (firstName
) de algún contacto y si la propiedad dada (prop
) es una propiedad de ese contacto.",
- "Si ambos son verdaderos, entonces retorna el valor (value
) de esa propiedad.",
- "Si firstName
no corresponde a ningun contacto entonces retorna \"No such contact\"
",
- "Si prop
no corresponde a ninguna propiedad válida entonces retorna \"No such property\"
",
- ""
- ]
- }
- }
- },
- {
- "id": "cf1111c1c11feddfaeb9bdef",
- "title": "Generate Random Fractions with JavaScript",
- "description": [
- "Random numbers are useful for creating random behavior.",
- "JavaScript has a Math.random()
function that generates a random decimal number between 0
(inclusive) and not quite up to 1
(exclusive). Thus Math.random()
can return a 0
but never quite return a 1
",
- "Note
Like Storing Values with the Equal Operator, all function calls will be resolved before the return
executes, so we can return
the value of the Math.random()
function.",
- "
",
- "Change randomFraction
to return a random number instead of returning 0
."
- ],
- "challengeSeed": [
- "function randomFraction() {",
- "",
- " // Only change code below this line.",
- "",
- " return 0;",
- "",
- " // Only change code above this line.",
- "}"
- ],
- "tail": [
- "(function(){return randomFraction();})();"
- ],
- "solutions": [
- "function randomFraction() {\n return Math.random();\n}"
- ],
- "tests": [
- "assert(typeof randomFraction() === \"number\", 'message: randomFraction
should return a random number.');",
- "assert((randomFraction()+''). match(/\\./g), 'message: The number returned by randomFraction
should be a decimal.');",
- "assert(code.match(/Math\\.random/g).length >= 0, 'message: You should be using Math.random
to generate the random decimal number.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Generar fracciones al azar con JavaScript",
- "description": [
- "Los números aleatorios son útiles para crear un comportamiento aleatorio.",
- "JavaScript tiene una función Math.random()
que genera un número decimal aleatorio.",
- "Instrucciones
",
- "Cambia randomFraction
para que devuelva un número al azar en lugar de devolver 0
.",
- "Ten en cuenta que puedes retornar lo retornado por una función, igual que harías para devolver una variable o valor."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c12feddfaeb1bdef",
- "title": "Generate Random Whole Numbers with JavaScript",
- "description": [
- "It's great that we can generate random decimal numbers, but it's even more useful if we use it to generate random whole numbers.",
- "
",
- "Remember that Math.random()
to generate a random decimal.20
.Math.floor()
to round the number down to its nearest whole number.Math.random()
can never quite return a 1
and, because we're rounding down, it's impossible to actually get 20
. This technique will give us a whole number between 0
and 19
.",
- "Putting everything together, this is what our code looks like:",
- "Math.floor(Math.random() * 20);
",
- "We are calling Math.random()
, multiplying the result by 20, then passing the value to Math.floor()
function to round the value down to the nearest whole number.",
- "
",
- "Use this technique to generate and return a random whole number between 0
and 9
."
- ],
- "challengeSeed": [
- "var randomNumberBetween0and19 = Math.floor(Math.random() * 20);",
- "",
- "function randomWholeNum() {",
- "",
- " // Only change code below this line.",
- "",
- " return Math.random();",
- "}"
- ],
- "tail": [
- "(function(){return randomWholeNum();})();"
- ],
- "solutions": [
- "var randomNumberBetween0and19 = Math.floor(Math.random() * 20);\nfunction randomWholeNum() {\n return Math.floor(Math.random() * 10);\n}"
- ],
- "tests": [
- "assert(typeof randomWholeNum() === \"number\" && (function(){var r = randomWholeNum();return Math.floor(r) === r;})(), 'message: The result of randomWholeNum
should be a whole number.');",
- "assert(code.match(/Math.random/g).length > 1, 'message: You should be using Math.random
to generate a random number.');",
- "assert(code.match(/\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?\\*\\s*?10[\\D]\\s*?/g) || code.match(/\\s*?10\\s*?\\*\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?/g), 'message: You should have multiplied the result of Math.random
by 10 to make it a number that is between zero and nine.');",
- "assert(code.match(/Math.floor/g).length > 1, 'message: You should use Math.floor
to remove the decimal part of the number.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Genera números aleatorios enteros con JavaScript",
- "description": [
- "Es muy bueno que podamos generar números decimales al azar, pero es aún más útil si lo utilizamos para generar números enteros aleatorios.",
- "En primer lugar, vamos a usar Math.random()
para generar un decimal aleatorio.",
- "Entonces vamos a multiplicar este decimal azar por 20.",
- "Por último, vamos a usar otra función, Math.floor()
para redondear el número hasta su número entero más próximo.",
- "Esta técnica nos da un número entero entre 0 y 19.",
- "Tenga en cuenta que debido a que estamos redondeando, es imposible obtener 20.",
- "Poniendo todo junto, así es como se ve nuestro código:",
- "Math.floor(Math.random() * 20);
",
- "¿Ves como Math.floor
toma (Math.random() * 20)
como su argumento? Así es - puedes pasar el resultado de un función como argumento de otra función.",
- "Instrucciones
",
- "Usa esta técnica para generar y devolver un número entero aleatorio entre 0 y 9."
- ]
- }
- }
- },
- {
- "id": "cf1111c1c12feddfaeb2bdef",
- "title": "Generate Random Whole Numbers within a Range",
- "description": [
- "Instead of generating a random number between zero and a given number like we did before, we can generate a random number that falls within a range of two specific numbers.",
- "To do this, we'll define a minimum number min
and a maximum number max
.",
- "Here's the formula we'll use. Take a moment to read it and try to understand what this code is doing:",
- "Math.floor(Math.random() * (max - min + 1)) + min
",
- "
",
- "Create a function called randomRange
that takes a range myMin
and myMax
and returns a random number that's greater than or equal to myMin
, and is less than or equal to myMax
, inclusive."
- ],
- "challengeSeed": [
- "// Example",
- "function ourRandomRange(ourMin, ourMax) {",
- "",
- " return Math.floor(Math.random() * (ourMax - ourMin + 1)) + ourMin;",
- "}",
- "",
- "ourRandomRange(1, 9);",
- "",
- "// Only change code below this line.",
- "",
- "function randomRange(myMin, myMax) {",
- "",
- " return 0; // Change this line",
- "",
- "}",
- "",
- "// Change these values to test your function",
- "var myRandom = randomRange(5, 15);"
- ],
- "tail": [
- "var calcMin = 100;",
- "var calcMax = -100;",
- "for(var i = 0; i < 100; i++) {",
- " var result = randomRange(5,15);",
- " calcMin = Math.min(calcMin, result);",
- " calcMax = Math.max(calcMax, result);",
- "}",
- "(function(){",
- " if(typeof myRandom === 'number') {",
- " return \"myRandom = \" + myRandom;",
- " } else {",
- " return \"myRandom undefined\";",
- " }",
- "})();"
- ],
- "solutions": [
- "function randomRange(myMin, myMax) {\n return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;\n}"
- ],
- "tests": [
- "assert(calcMin === 5, 'message: The lowest random number that can be generated by randomRange
should be equal to your minimum number, myMin
.');",
- "assert(calcMax === 15, 'message: The highest random number that can be generated by randomRange
should be equal to your maximum number, myMax
.');",
- "assert(randomRange(0,1) % 1 === 0 , 'message: The random number generated by randomRange
should be an integer, not a decimal.');",
- "assert((function(){if(code.match(/myMax/g).length > 1 && code.match(/myMin/g).length > 2 && code.match(/Math.floor/g) && code.match(/Math.random/g)){return true;}else{return false;}})(), 'message: randomRange
should use both myMax
and myMin
, and return a random number in your range.');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {
- "es": {
- "title": "Genera números aleatorios enteros dentro de un rango",
- "description": [
- "En lugar de generar un número aleatorio entre cero y un número dado como lo hicimos antes, podemos generar un número aleatorio que caiga dentro de un rango de dos números específicos.",
- "Para ello, vamos a definir un número mínimo min
y un número máximo max
.",
- "He aquí la fórmula que utilizaremos. Tómate un momento para leer y tratar de entender lo que el código está haciendo: ",
- "Math.floor(Math.random() * (max - min + 1)) + min
",
- "Definir dos variables: myMin
y myMax
, y asignales valores enteros.",
- "Instrucciones
",
- "A continuación, crea una función llamada myFunction
que devuelva un número aleatorio mayor o igual a myMin
, y menor o igual a myMax
. "
- ]
- }
- }
- },
- {
- "id": "587d7b7e367417b2b2512b23",
- "title": "Use the parseInt Function",
- "description": [
- "The parseInt()
function parses a string and returns an integer. Here's an example:",
- "var a = parseInt(\"007\");
",
- "The above function converts the string \"007\" to an integer 7. If the first character in the string can't be converted into a number, then it returns NaN
.",
- "
",
- "Use parseInt()
in the convertToInteger
function so it converts the input string str
into an integer, and returns it."
- ],
- "challengeSeed": [
- "function convertToInteger(str) {",
- " ",
- "}",
- "",
- "convertToInteger(\"56\");"
- ],
- "tail": [],
- "solutions": [],
- "tests": [
- "assert(/parseInt/g.test(code), 'message: convertToInteger
should use the parseInt()
function');",
- "assert(typeof(convertToInteger(\"56\")) === \"number\", 'message: convertToInteger(\"56\")
should return a number');",
- "assert(convertToInteger(\"56\") === 56, 'message: convertToInteger(\"56\")
should return 56');",
- "assert(convertToInteger(\"77\") === 77, 'message: convertToInteger(\"77\")
should return 77');",
- "assert.isNaN(convertToInteger(\"JamesBond\"), 'message: convertToInteger(\"JamesBond\")
should return NaN');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {},
- "releasedOn": "February 17, 2017"
- },
- {
- "id": "587d7b7e367417b2b2512b22",
- "title": "Use the parseInt Function with a Radix",
- "description": [
- "The parseInt()
function parses a string and returns an integer. It takes a second argument for the radix, which specifies the base of the number in the string. The radix can be an integer between 2 and 36.",
- "The function call looks like:",
- "parseInt(string, radix);
",
- "And here's an example:",
- "var a = parseInt(\"11\", 2);
",
- "The radix variable says that \"11\" is in the binary system, or base 2. This example converts the string \"11\" to an integer 3.",
- "
",
- "Use parseInt()
in the convertToInteger
function so it converts a binary number to an integer and returns it."
- ],
- "challengeSeed": [
- "function convertToInteger(str) {",
- " ",
- "}",
- "",
- "convertToInteger(\"10011\");"
- ],
- "tail": [],
- "solutions": [],
- "tests": [
- "assert(/parseInt/g.test(code), 'message: convertToInteger
should use the parseInt()
function');",
- "assert(typeof(convertToInteger(\"10011\")) === \"number\", 'message: convertToInteger(\"10011\")
should return a number');",
- "assert(convertToInteger(\"10011\") === 19, 'message: convertToInteger(\"10011\")
should return 19');",
- "assert(convertToInteger(\"111001\") === 57, 'message: convertToInteger(\"111001\")
should return 57');",
- "assert.isNaN(convertToInteger(\"JamesBond\"), 'message: convertToInteger(\"JamesBond\")
should return NaN');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "releasedOn": "February 17, 2017",
- "translations": {}
- },
- {
- "id": "587d7b7e367417b2b2512b24",
- "title": "Use the Conditional (Ternary) Operator",
- "description": [
- "The conditional operator, also called the ternary operator, can be used as a one line if-else expression.",
- "The syntax is:",
- "condition ? statement-if-true : statement-if-false;
",
- "The following function uses an if-else statement to check a condition:",
- "function findGreater(a, b) {
",
- "This can be re-written using the
if(a > b) {
return \"a is greater\";
}
else {
return \"b is greater\";
}
}conditional operator
:",
- "function findGreater(a, b) {
",
- "
return a > b ? \"a is greater\" : \"b is greater\";
}
",
- "Use the conditional operator
in the checkEqual
function to check if two numbers are equal or not. The function should return either true or false."
- ],
- "challengeSeed": [
- "function checkEqual(a, b) {",
- " ",
- "}",
- "",
- "checkEqual(1, 2);"
- ],
- "tail": [],
- "solutions": [],
- "tests": [
- "assert(/.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?/gi.test(code), 'message: checkEqual
should use the conditional operator
');",
- "assert(checkEqual(1, 2) === false, 'message: checkEqual(1, 2)
should return false');",
- "assert(checkEqual(1, 1) === true, 'message: checkEqual(1, 1)
should return true');",
- "assert(checkEqual(1, -1) === false, 'message: checkEqual(1, -1)
should return false');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "releasedOn": "February 17, 2017",
- "translations": {}
- },
- {
- "id": "587d7b7e367417b2b2512b21",
- "title": "Use Multiple Conditional (Ternary) Operators",
- "description": [
- "In the previous challenge, you used a single conditional operator
. You can also chain them together to check for multiple conditions.",
- "The following function uses if, else if, and else statements to check multiple conditions:",
- "function findGreaterOrEqual(a, b) {
",
- "The above function can be re-written using multiple
if(a === b) {
return \"a and b are equal\";
}
else if(a > b) {
return \"a is greater\";
}
else {
return \"b is greater\";
}
}conditional operators
:",
- "function findGreaterOrEqual(a, b) {
",
- "
return (a === b) ? \"a and b are equal\" : (a > b) ? \"a is greater\" : \"b is greater\";
}
",
- "Use multiple conditional operators
in the checkSign
function to check if a number is positive, negative or zero."
- ],
- "challengeSeed": [
- "function checkSign(num) {",
- " ",
- "}",
- "",
- "checkSign(10);"
- ],
- "tail": [],
- "solutions": [],
- "tests": [
- "assert(/.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?/gi.test(code), 'message: checkSign
should use multiple conditional operators
');",
- "assert(checkSign(10) === 'positive', 'message: checkSign(10)
should return \"positive\". Note that capitalization matters');",
- "assert(checkSign(-12) === 'negative', 'message: checkSign(-12)
should return \"negative\". Note that capitalization matters');",
- "assert(checkSign(0) === 'zero', 'message: checkSign(0)
should return \"zero\". Note that capitalization matters');"
- ],
- "type": "waypoint",
- "challengeType": 1,
- "releasedOn": "February 17, 2017",
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json
deleted file mode 100644
index d308cc9c86..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json
+++ /dev/null
@@ -1,423 +0,0 @@
-{
- "name": "Debugging",
- "order": 4,
- "time": "1 hour",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7b83367417b2b2512b32",
- "title": "Introduction to the Debugging Challenges",
- "description": [
- "",
- "",
- "Debugging is a valuable and (unfortunately) necessary tool for programmers. It follows the testing phase of checking if your code works as intended, and discovering it does not. Debugging is the process of finding exactly what isn't working and fixing it.",
- "",
- "@@STEP@@",
- "",
- "",
- "After spending time creating a brilliant block of code, it is tough realizing it may have errors. These issues generally come in three forms: 1) syntax errors that prevent a program from running, 2) runtime errors when code fails to execute or has unexpected behavior, and 3) semantic (or logical) errors when code doesn't do what it's meant to.
Modern code editors (and experience) can help identify syntax errors. Semantic and runtime errors are harder to find. They may cause your program to crash, make it run forever, or give incorrect output. Think of debugging as trying to understand why your code is behaving the way it is.
Example of a syntax error - often detected by the code editor:funtion willNotWork( {
console.log(\"Yuck\");
}
// \"function\" keyword is misspelled and there's a missing parenthesis
Here's an example of a runtime error - often detected while the program executes:function loopy() {
while(true) {
console.log(\"Hello, world!\");
}
}
// Calling loopy starts an infinite loop, which may crash your browser
Example of a semantic error - often detected after testing code output:function calcAreaOfRect(w, h) {
",
- "",
- "@@STEP@@",
- "",
- "",
- "Debugging is frustrating, but it helps to develop (and follow) a step-by-step approach to review your code. This means checking the intermediate values and types of variables to see if they are what they should be. You can start with a simple process of elimination.
return w + h; // This should be w * h
}
let myRectArea = calcAreaOfRect(2, 3);
// Correct syntax and the program executes, but this gives the wrong answer
For example, if function A works and returns what it's supposed to, then function B may have the issue. Or start checking values in a block of code from the middle to try to cut the search space in half. A problem in one spot indicates a bug in the first half of the code. If not, it's likely in the second.
This section will cover a couple helpful tools to find bugs, and some of the common forms they take. Fortunately, debugging is a learnable skill that just requires a little patience and practice to master.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7b83367417b2b2512b33",
- "title": "Use the JavaScript Console to Check the Value of a Variable",
- "description": [
- "Both Chrome and Firefox have excellent JavaScript consoles, also known as DevTools, for debugging your JavaScript.",
- "You can find Developer tools in your Chrome's menu or Web Console in FireFox's menu. If you're using a different browser, or a mobile phone, we strongly recommend switching to desktop Firefox or Chrome.",
- "The console.log()
method, which \"prints\" the output of what's within its parentheses to the console, will likely be the most helpful debugging tool. Placing it at strategic points in your code can show you the intermediate values of variables. It's good practice to have an idea of what the output should be before looking at what it is. Having check points to see the status of your calculations throughout your code will help narrow down where the problem is.",
- "Here's an example to print 'Hello world!' to the console:",
- "console.log('Hello world!');
",
- "
",
- "Use the console.log()
method to print the value of the variable a
where noted in the code."
- ],
- "challengeSeed": [
- "let a = 5;",
- "let b = 1;",
- "a++;",
- "// Add your code below this line",
- "",
- "",
- "let sumAB = a + b;",
- "console.log(sumAB);"
- ],
- "tests": [
- "assert(code.match(/console\\.log\\(a\\)/g), 'message: Your code should use console.log()
to check the value of the variable a
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b83367417b2b2512b37",
- "title": "Understanding the Differences between the freeCodeCamp and Browser Console",
- "description": [
- "You may have noticed that some freeCodeCamp JavaScript challenges include their own console. This console behaves a little differently than the browser console you used in the last challenge.",
- "The following challenge is meant to highlight some of the differences between the freeCodeCamp console and the browser console.",
- "First, the browser console. When you load and run an ordinary JavaScript file in your browser the console.log()
statements will print exactly what you tell them to print to the browser console the exact number of times you requested. In your in-browser text editor the process is slightly different and can be confusing at first.",
- "Values passed to console.log()
in the text editor block run each set of tests as well as one more time for any function calls that you have in you code.",
- "This lends itself to some interesting behavior and might trip you up in the beginning, because a logged value that you expect to see only once may print out many more times depending on the number of tests and the values being passed to those tests.",
- "If you would like to see only your single output and not have to worry about running through the test cycles, you can use console.clear()
.",
- "
",
- "Use console.log()
to print the variables in the code where indicated.",
- ""
- ],
- "challengeSeed": [
- "// Open your browser console",
- "let outputTwo = \"This will print to the browser console 2 times\";",
- "// Use console.log() to print the outputTwo variable",
- "",
- "",
- "let outputOne = \"Try to get this to log only once to the browser console\";",
- "// Use console.clear() in the next line to print the outputOne only once",
- "",
- "",
- "// Use console.log() to print the outputOne variable",
- "",
- ""
- ],
- "tests": [
- "assert(code.match(/console\\.log\\(outputTwo\\)/g), 'message: Use console.log()
to print the outputTwice
variable. In your Browser Console this should print out the value of the variable two times.');",
- "assert(code.match(/console\\.log\\(outputOne\\)/g), 'message: Use console.log()
to print the outputOne
variable.');",
- "assert(code.match(/console\\.clear\\(\\)/g), 'message: Use console.clear()
to modify your output so that outputOne
variable only outputs once.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b84367417b2b2512b34",
- "title": "Use typeof to Check the Type of a Variable",
- "description": [
- "You can use typeof
to check the data structure, or type, of a variable. This is useful in debugging when working with multiple data types. If you think you're adding two numbers, but one is actually a string, the results can be unexpected. Type errors can lurk in calculations or function calls. Especially take care when you're accessing and working with external data in the form of a JavaScript object (JSON).",
- "Here are some examples using typeof
:",
- "console.log(typeof \"\"); // outputs \"string\"
",
- "JavaScript recognizes six primitive (immutable) data types:
console.log(typeof 0); // outputs \"number\"
console.log(typeof []); // outputs \"object\"
console.log(typeof {}); // outputs \"object\"Boolean
, Null
, Undefined
, Number
, String
, and Symbol
(new with ES6) and one type for mutable items: Object
. Note that in JavaScript, arrays are technically a type of object.",
- "
",
- "Add two console.log()
statements to check the typeof
each of the two variables seven
and three
in the code."
- ],
- "challengeSeed": [
- "let seven = 7;",
- "let three = \"3\";",
- "console.log(seven + three);",
- "// Add your code below this line",
- ""
- ],
- "tests": [
- "assert(code.match(/console\\.log\\(typeof[\\( ].*\\)?\\)/g).length == 2, 'message: Your code should use typeof
in two console.log()
statements to check the type of the variables.');",
- "assert(code.match(/typeof[\\( ]seven\\)?/g), 'message: Your code should use typeof
to check the type of the variable seven
.');",
- "assert(code.match(/typeof[\\( ]three\\)?/g), 'message: Your code should use typeof
to check the type of the variable three
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b84367417b2b2512b35",
- "title": "Catch Misspelled Variable and Function Names",
- "description": [
- "The console.log()
and typeof
methods are the two primary ways to check intermediate values and types of program output. Now it's time to get into the common forms that bugs take. One syntax-level issue that fast typers can commiserate with is the humble spelling error.",
- "Transposed, missing, or mis-capitalized characters in a variable or function name will have the browser looking for an object that doesn't exist - and complain in the form of a reference error. JavaScript variable and function names are case-sensitive.",
- "
",
- "Fix the two spelling errors in the code so the netWorkingCapital
calculation works."
- ],
- "challengeSeed": [
- "let receivables = 10;",
- "let payables = 8;",
- "let netWorkingCapital = recievables - payable;",
- "console.log(`Net working capital is: ${netWorkingCapital}`);"
- ],
- "tests": [
- "assert(netWorkingCapital === 2, 'message: Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that \"Net working capital is: 2\".');",
- "assert(!code.match(/recievables/g), 'message: There should be no instances of mis-spelled variables in the code.');",
- "assert(code.match(/receivables/g).length == 2, 'message: The receivables
variable should be declared and used properly in the code.');",
- "assert(!code.match(/payable;/g), 'message: There should be no instances of mis-spelled variables in the code.');",
- "assert(code.match(/payables/g).length == 2, 'message: The payables
variable should be declared and used properly in the code.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b84367417b2b2512b36",
- "title": "Catch Unclosed Parentheses, Brackets, Braces and Quotes",
- "description": [
- "Another syntax error to be aware of is that all opening parentheses, brackets, curly braces, and quotes have a closing pair. Forgetting a piece tends to happen when you're editing existing code and inserting items with one of the pair types. Also, take care when nesting code blocks into others, such as adding a callback function as an argument to a method.",
- "One way to avoid this mistake is as soon as the opening character is typed, immediately include the closing match, then move the cursor back between them and continue coding. Fortunately, most modern code editors generate the second half of the pair automatically.",
- "
",
- "Fix the two pair errors in the code."
- ],
- "challengeSeed": [
- "let myArray = [1, 2, 3;",
- "let arraySum = myArray.reduce((previous, current => previous + current);",
- "console.log(`Sum of array values is: ${arraySum}`);"
- ],
- "tests": [
- "assert(code.match(/myArray\\s*?=\\s*?\\[\\s*?1\\s*?,\\s*?2\\s*?,\\s*?3\\s*?\\];/g), 'message: Your code should fix the missing piece of the array.');",
- "assert(arraySum === 6, 'message: Your code should fix the missing piece of the .reduce()
method. The console output should show that \"Sum of array values is: 6\".');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b84367417b2b2512b37",
- "title": "Catch Mixed Usage of Single and Double Quotes",
- "description": [
- "JavaScript allows the use of both single ('') and double (\"\") quotes to declare a string. Deciding which one to use generally comes down to personal preference, with some exceptions.",
- "Having two choices is great when a string has contractions or another piece of text that's in quotes. Just be careful that you don't close the string too early, which causes a syntax error.",
- "Here are some examples of mixing quotes:",
- "// These are correct:
",
- "Of course, it is okay to use only one style of quotes. You can escape the quotes inside the string by using the backslash (\\) escape character:",
- "
const grouchoContraction = \"I've had a perfectly wonderful evening, but this wasn't it.\";
const quoteInString = \"Groucho Marx once said 'Quote me as saying I was mis-quoted.'\";
// This is incorrect:
const uhOhGroucho = 'I've had a perfectly wonderful evening, but this wasn't it.';// Correct use of same quotes:
",
- "
const allSameQuotes = 'I\\'ve had a perfectly wonderful evening, but this wasn\\'t it.';
",
- "Fix the string so it either uses different quotes for the href
value, or escape the existing ones. Keep the double quote marks around the entire string."
- ],
- "challengeSeed": [
- "let innerHtml = \"href
value \"#Home\" by either changing or escaping them.');",
- "assert(code.match(/\"if
, else if
, and else
statements in JavaScript. The condition sometimes takes the form of testing whether a result is equal to a value.",
- "This logic is spoken (in English, at least) as \"if x equals y, then ...\" which can literally translate into code using the =
, or assignment operator. This leads to unexpected control flow in your program.",
- "As covered in previous challenges, the assignment operator (=
) in JavaScript assigns a value to a variable name. And the ==
and ===
operators check for equality (the triple ===
tests for strict equality, meaning both value and type are the same).",
- "The code below assigns x
to be 2, which evaluates as true
. Almost every value on its own in JavaScript evaluates to true
, except what are known as the \"falsy\" values: false
, 0
, \"\"
(an empty string), NaN
, undefined
, and null
.",
- "let x = 1;
",
- "
let y = 2;
if (x = y) {
// this code block will run for any value of y (unless y were originally set as a falsy)
} else {
// this code block is what should run (but won't) in this example
}
",
- "Fix the condition so the program runs the right branch, and the appropriate value is assigned to result
."
- ],
- "challengeSeed": [
- "let x = 7;",
- "let y = 9;",
- "let result = \"to come\";",
- "",
- "if(x = y) {",
- " result = \"Equal!\";",
- "} else {",
- " result = \"Not equal!\";",
- "}",
- "",
- "console.log(result);"
- ],
- "tests": [
- "assert(result == \"Not equal!\", 'message: Your code should fix the condition so it checks for equality, instead of using assignment.');",
- "assert(code.match(/x\\s*?===?\\s*?y/g), 'message: The condition can use either ==
or ===
to test for equality.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b85367417b2b2512b39",
- "title": "Catch Missing Open and Closing Parenthesis After a Function Call",
- "description": [
- "When a function or method doesn't take any arguments, you may forget to include the (empty) opening and closing parentheses when calling it. Often times the result of a function call is saved in a variable for other use in your code. This error can be detected by logging variable values (or their types) to the console and seeing that one is set to a function reference, instead of the expected value the function returns.",
- "The variables in the following example are different:",
- "function myFunction() {
",
- "
return \"You rock!\";
}
let varOne = myFunction; // set to equal a function
let varTwo = myFunction(); // set to equal the string \"You rock!\"
",
- "Fix the code so the variable result
is set to the value returned from calling the function getNine
."
- ],
- "challengeSeed": [
- "function getNine() {",
- " let x = 6;",
- " let y = 3;",
- " return x + y;",
- "}",
- "",
- "let result = getNine;",
- "console.log(result);"
- ],
- "tests": [
- "assert(result == 9, 'message: Your code should fix the variable result
so it is set to the number that the function getNine
returns.');",
- "assert(code.match(/getNine\\(\\)/g).length == 2, 'message: Your code should call the getNine
function.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b85367417b2b2512b3a",
- "title": "Catch Arguments Passed in the Wrong Order When Calling a Function",
- "description": [
- "Continuing the discussion on calling functions, the next bug to watch out for is when a function's arguments are supplied in the incorrect order. If the arguments are different types, such as a function expecting an array and an integer, this will likely throw a runtime error. If the arguments are the same type (all integers, for example), then the logic of the code won't make sense. Make sure to supply all required arguments, in the proper order to avoid these issues.",
- "
",
- "The function raiseToPower
raises a base to an exponent. Unfortunately, it's not called properly - fix the code so the value of power
is the expected 8."
- ],
- "challengeSeed": [
- "function raiseToPower(b, e) {",
- " return Math.pow(b, e);",
- "}",
- "",
- "let base = 2;",
- "let exp = 3;",
- "let power = raiseToPower(exp, base);",
- "console.log(power);"
- ],
- "tests": [
- "assert(power == 8, 'message: Your code should fix the variable power
so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.');",
- "assert(code.match(/raiseToPower\\(\\s*?base\\s*?,\\s*?exp\\s*?\\);/g), 'message: Your code should use the correct order of the arguments for the raiseToPower
function call.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b86367417b2b2512b3b",
- "title": "Catch Off By One Errors When Using Indexing",
- "description": [
- "Off by one errors
(sometimes called OBOE) crop up when you're trying to target a specific index of a string or array (to slice or access a segment), or when looping over the indices of them. JavaScript indexing starts at zero, not one, which means the last index is always one less than the length of the item. If you try to access an index equal to the length, the program may throw an \"index out of range\" reference error or print undefined
.",
- "When you use string or array methods that take index ranges as arguments, it helps to read the documentation and understand if they are inclusive (the item at the given index is part of what's returned) or not. Here are some examples of off by one errors:",
- "let alphabet = \"abcdefghijklmnopqrstuvwxyz\";
",
- "
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
// loops one too many times at the end
console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
// loops one too few times and misses the first character at index 0
console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
// Goldilocks approves - this is just right
console.log(alphabet[k]);
}
",
- "Fix the two indexing errors in the following function so all the numbers 1 through 5 are printed to the console."
- ],
- "challengeSeed": [
- "function countToFive() {",
- " let firstFive = \"12345\";",
- " let len = firstFive.length;",
- " // Fix the line below",
- " for (let i = 1; i <= len; i++) {",
- " // Do not alter code below this line",
- " console.log(firstFive[i]);",
- " }",
- "}",
- "",
- "countToFive();"
- ],
- "tests": [
- "assert(code.match(/i\\s*?=\\s*?0\\s*?;/g).length == 1, 'message: Your code should set the initial condition of the loop so it starts at the first index.');",
- "assert(!code.match(/i\\s?=\\s*?1\\s*?;/g), 'message: Your code should fix the initial condition of the loop so that the index starts at 0.');",
- "assert(code.match(/i\\s*?<\\s*?len\\s*?;/g).length == 1, 'message: Your code should set the terminal condition of the loop so it stops at the last index.');",
- "assert(!code.match(/i\\s*?<=\\s*?len;/g), 'message: Your code should fix the terminal condition of the loop so that it stops at 1 before the length.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b86367417b2b2512b3c",
- "title": "Use Caution When Reinitializing Variables Inside a Loop",
- "description": [
- "Sometimes it's necessary to save information, increment counters, or re-set variables within a loop. A potential issue is when variables either should be reinitialized, and aren't, or vice versa. This is particularly dangerous if you accidentally reset the variable being used for the terminal condition, causing an infinite loop.",
- "Printing variable values with each cycle of your loop by using console.log()
can uncover buggy behavior related to resetting, or failing to reset a variable.",
- "
",
- "The following function is supposed to create a two-dimensional array with m
rows and n
columns of zeroes. Unfortunately, it's not producing the expected output because the row
variable isn't being reinitialized (set back to an empty array) in the outer loop. Fix the code so it returns a correct 3x2 array of zeroes, which looks like [[0, 0], [0, 0], [0, 0]]
."
- ],
- "challengeSeed": [
- "function zeroArray(m, n) {",
- " // Creates a 2-D array with m rows and n columns of zeroes",
- " let newArray = [];",
- " let row = [];",
- " for (let i = 0; i < m; i++) {",
- " // Adds the m-th row into newArray",
- " ",
- " for (let j = 0; j < n; j++) {",
- " // Pushes n zeroes into the current row to create the columns",
- " row.push(0);",
- " }",
- " // Pushes the current row, which now has n zeroes in it, to the array",
- " newArray.push(row);",
- " }",
- " return newArray;",
- "}",
- "",
- "let matrix = zeroArray(3, 2);",
- "console.log(matrix);"
- ],
- "tests": [
- "assert(JSON.stringify(matrix) == \"[[0,0],[0,0],[0,0]]\", 'message: Your code should set the matrix
variable to an array holding 3 rows of 2 columns of zeroes each.');",
- "assert(matrix.length == 3, 'message: The matrix
variable should have 3 rows.');",
- "assert(matrix[0].length == 2 && matrix[1].length === 2 && matrix[2].length === 2, 'message: The matrix
variable should have 2 columns in each row.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b86367417b2b2512b3d",
- "title": "Prevent Infinite Loops with a Valid Terminal Condition",
- "description": [
- "The final topic is the dreaded infinite loop. Loops are great tools when you need your program to run a code block a certain number of times or until a condition is met, but they need a terminal condition that ends the looping. Infinite loops are likely to freeze or crash the browser, and cause general program execution mayhem, which no one wants.",
- "There was an example of an infinite loop in the introduction to this section - it had no terminal condition to break out of the while
loop inside loopy()
. Do NOT call this function!",
- "function loopy() {
",
- "It's the programmer's job to ensure that the terminal condition, which tells the program when to break out of the loop code, is eventually reached. One error is incrementing or decrementing a counter variable in the wrong direction from the terminal condition. Another one is accidentally resetting a counter or index variable within the loop code, instead of incrementing or decrementing it.",
- "
while(true) {
console.log(\"Hello, world!\");
}
}
",
- "The myFunc()
function contains an infinite loop because the terminal condition i != 4
will never evaluate to false
(and break the looping) - i
will increment by 2 each pass, and jump right over 4 since i
is odd to start. Fix the comparison operator in the terminal condition so the loop only runs for i
less than or equal to 4."
- ],
- "challengeSeed": [
- "function myFunc() {",
- " for (let i = 1; i != 4; i += 2) {",
- " console.log(\"Still going!\");",
- " }",
- "}"
- ],
- "tests": [
- "assert(code.match(/i\\s*?<=\\s*?4;/g).length == 1, 'message: Your code should change the comparison operator in the terminal condition (the middle part) of the for
loop.');",
- "assert(!code.match(/i\\s*?!=\\s*?4;/g), 'message: Your code should fix the comparison operator in the terminal condition of the loop.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json
deleted file mode 100644
index 7a72cc1302..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json
+++ /dev/null
@@ -1,971 +0,0 @@
-{
- "name": "ES6",
- "order": 2,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7b86367417b2b2512b3e",
- "title": "Introduction to the ES6 Challenges",
- "description": [
- "",
- "",
- "ECMAScript is a standardized version of JavaScript with the goal of unifying the language's specifications and features. As all major browsers and JavaScript-runtimes follow this specification, the term ECMAScript is interchangeable with the term JavaScript.
Most of the challenges on freeCodeCamp use the ECMAScript 5 (ES5) specification of the language, finalized in 2009. But JavaScript is an evolving programming language. As features are added and revisions are made, new versions of the language are released for use by developers.
The most recent standardized version is called ECMAScript 6 (ES6), released in 2015. This new version of the language adds some powerful features that will be covered in this section of challenges, including:let
and const
Note
Not all browsers support ES6 features. If you use ES6 in your own projects, you may need to use a program (transpiler) to convert your ES6 code into ES5 until browsers support ES6.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7b87367417b2b2512b3f",
- "title": "Explore Differences Between the var and let Keywords",
- "description": [
- "One of the biggest problems with declaring variables with the var
keyword is that you can overwrite variable declarations without an error.",
- "var camper = 'James';
",
- "As you can see in the code above, the
var camper = 'David';
console.log(camper);
// logs 'David'camper
variable is originally declared as James
and then overridden to be David
.",
- "In a small application, you might not run into this type of problem, but when your code becomes larger, you might accidently overwrite a variable that you did not intend to overwrite.",
- "Because this behavior does not throw an error, searching and fixing bugs becomes more difficult.
",
- "A new keyword called let
was introduced in ES6 to solve this potential issue with the var
keyword.",
- "If you were to replace var
with let
in the variable declarations of the code above, the result would be an error.",
- "let camper = 'James';
",
- "This error can be seen in the console of your browser.",
- "So unlike
let camper = 'David'; // throws an errorvar
, when using let
, a variable with the same name can only be declared once.",
- "Note the \"use strict\"
. This enables Strict Mode, which catches common coding mistakes and \"unsafe\" actions. For instance:",
- "\"use strict\";
",
- "
x = 3.14; // throws an error because x is not declared
",
- "Update the code so it only uses the let
keyword."
- ],
- "challengeSeed": [
- "var catName;",
- "var quote;",
- "function catTalk() {",
- " \"use strict\";",
- "",
- " catName = \"Oliver\";",
- " quote = catName + \" says Meow!\";",
- "",
- "}",
- "catTalk();"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var
does not exist in code.');",
- "assert(catName === \"Oliver\", 'message: catName
should be Oliver
.');",
- "assert(quote === \"Oliver says Meow!\", 'message: quote
should be \"Oliver says Meow!\"
');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b87367417b2b2512b40",
- "title": "Compare Scopes of the var and let Keywords",
- "description": [
- "When you declare a variable with the var
keyword, it is declared globally, or locally if declared inside a function.",
- "The let
keyword behaves similarly, but with some extra features. When you declare a variable with the let
keyword inside a block, statement, or expression, its scope is limited to that block, statement, or expression.",
- "For example:",
- "var numArray = [];
",
- "With the
for (var i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3var
keyword, i
is declared globally. So when i++
is executed, it updates the global variable. This code is similiar to the following:",
- "var numArray = [];
",
- "This behavior will cause problems if you were to create a function and store it for later use inside a for loop that uses the
var i;
for (i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3i
variable. This is because the stored function will always refer to the value of the updated global i
variable.",
- "var printNumTwo;
",
- "As you can see,
for (var i = 0; i < 3; i++) {
if(i === 2){
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 3printNumTwo()
prints 3 and not 2. This is because the value assigned to i
was updated and the printNumTwo()
returns the global i
and not the value i
had when the function was created in the for loop. The let
keyword does not follow this behavior:",
- "'use strict';
",
- "
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns \"i is not defined\"i
is not defined because it was not declared in the global scope. It is only declared within the for loop statement. printNumTwo()
returned the correct value because three different i
variables with unique values (0, 1, and 2) were created by the let
keyword within the loop statement.",
- "
",
- "Fix the code so that i
declared in the if statement is a separate variable than i
declared in the first line of the function. Be certain not to use the var
keyword anywhere in your code.",
- "This exercise is designed to illustrate the difference between how var
and let
keywords assign scope to the declared variable. When programming a function similar to the one used in this exercise, it is often better to use different variable names to avoid confusion."
- ],
- "challengeSeed": [
- "",
- "function checkScope() {",
- "\"use strict\";",
- " var i = \"function scope\";",
- " if (true) {",
- " i = \"block scope\";",
- " console.log(\"Block scope i is: \", i);",
- " }",
- " console.log(\"Function scope i is: \", i);",
- " return i;",
- "}"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var
does not exist in code.');",
- "getUserInput => assert(getUserInput('index').match(/(i\\s*=\\s*).*\\s*.*\\s*.*\\1('|\")block\\s*scope\\2/g), 'message: The variable i
declared in the if statement should equal \"block scope\".');",
- "assert(checkScope() === \"function scope\", 'message: checkScope()
should return \"function scope\"');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b87367417b2b2512b41",
- "title": "Declare a Read-Only Variable with the const Keyword",
- "description": [
- "let
is not the only new way to declare variables. In ES6, you can also declare variables using the const
keyword.",
- "const
has all the awesome features that let
has, with the added bonus that variables declared using const
are read-only. They are a constant value, which means that once a variable is assigned with const
, it cannot be reassigned.",
- "\"use strict\"
",
- "As you can see, trying to reassign a variable declared with
const FAV_PET = \"Cats\";
FAV_PET = \"Dogs\"; // returns errorconst
will throw an error. You should always name variables you don't want to reassign using the const
keyword. This helps when you accidentally attempt to reassign a variable that is meant to stay constant. A common practice is to name your constants in all upper-cases and with an underscore to separate words (e.g. EXAMPLE_VARIABLE
).",
- "
",
- "Change the code so that all variables are declared using let
or const
. Use let
when you want the variable to change, and const
when you want the variable to remain constant. Also, rename variables declared with const
to conform to common practices, meaning constants should be in all caps"
- ],
- "challengeSeed": [
- "function printManyTimes(str) {",
- " \"use strict\";",
- "",
- " // change code below this line",
- "",
- " var sentence = str + \" is cool!\";",
- " for(var i = 0; i < str.length; i+=2) {",
- " console.log(str);",
- " }",
- "",
- " // change code above this line",
- "",
- "}",
- "printManyTimes(\"freeCodeCamp\");"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var
does not exist in code.');",
- "getUserInput => assert(getUserInput('index').match(/(const SENTENCE)/g), 'message: SENTENCE
should be a constant variable (by using const
).');",
- "getUserInput => assert(getUserInput('index').match(/(let i)/g), 'message: i
should be a variable only defined within the for loop scope (by usinglet
).');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b87367417b2b2512b42",
- "title": "Mutate an Array Declared with const",
- "description": [
- "The const
declaration has many use cases in modern JavaScript.",
- "Some developers prefer to assign all their variables using const
by default, unless they know they will need to reassign the value. Only in that case, they use let
.",
- "However, it is important to understand that objects (including arrays and functions) assigned to a variable using const
are still mutable. Using the const
declaration only prevents reassignment of the variable identifier.",
- "\"use strict\";
",
- "As you can see, you can mutate the object
const s = [5, 6, 7];
s = [1, 2, 3]; // throws error, trying to assign a const
s[2] = 45; // works just as it would with an array declared with var or let
console.log(s); // returns [5, 6, 45][5, 6, 7]
itself and the variable s
will still point to the altered array [5, 6, 45]
. Like all arrays, the array elements in s
are mutable, but because const
was used, you cannot use the variable identifier s
to point to a different array using the assignment operator.",
- "
",
- "An array is declared as const s = [5, 7, 2]
. Change the array to [2, 5, 7]
using various element assignment."
- ],
- "challengeSeed": [
- "const s = [5, 7, 2];",
- "function editInPlace() {",
- " \"use strict\";",
- " // change code below this line",
- "",
- " // s = [2, 5, 7]; <- this is invalid",
- "",
- " // change code above this line",
- "}",
- "editInPlace();"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/const/g), 'message: Do not replace const
keyword.');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+s/g), 'message: s
should be a constant variable (by using const
).');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+s\\s*=\\s*\\[\\s*5\\s*,\\s*7\\s*,\\s*2\\s*\\]\\s*;?/g), 'message: Do not change the original array declaration.');",
- "assert.deepEqual(s, [2, 5, 7], 'message: s
should be equal to [2, 5, 7]
.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "598f48a36c8c40764b4e52b3",
- "title": "Prevent Object Mutation",
- "description": [
- "As seen in previous challenge, const
declaration alone doesn't really protect your data from mutation. To ensure your data doesn't change, JavaScript provides a function Object.freeze
to prevent data mutation.",
- "Once the object is freezed, you can no longer add/update/delete properties from it. Any attempt at changing the object will be rejected without any error.",
- "\nlet obj = {\n name:\"FreeCodeCamp\"\n review:\"Awesome\"\n};\nObject.freeze(obj);\nobj.review = \"bad\"; //will be ignored. Mutation not allowed\nobj.newProp = \"Test\"; // will be ignored. Mutation not allowed\nconsole.log(obj); \n// { name: \"FreeCodeCamp\", review:\"Awesome\"}\n
",
- "
",
- "In this challenge you are going to use Object.freeze
to prevent mathematical constants from changing. You need to freeze MATH_CONSTANTS
object so that noone is able alter the value of PI
or add any more properties to it."
- ],
- "challengeSeed": [
- "function freezeObj() {",
- " \"use strict\";",
- " const MATH_CONSTANTS = {",
- " PI: 3.14",
- " };",
- " // change code below this line",
- "",
- "",
- " // change code above this line",
- " try {",
- " MATH_CONSTANTS.PI = 99;",
- " } catch( ex ) {",
- " console.log(ex);",
- " }",
- " return MATH_CONSTANTS.PI;",
- "}",
- "const PI = freezeObj();"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/const/g), 'message: Do not replace const
keyword.');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+MATH_CONSTANTS/g), 'message: MATH_CONSTANTS
should be a constant variable (by using const
).');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+MATH_CONSTANTS\\s+=\\s+{\\s+PI:\\s+3.14\\s+};/g), 'message: Do not change original MATH_CONSTANTS
.');",
- "assert(PI === 3.14, 'message: PI
equals 3.14
.');"
- ],
- "type": "waypoint",
- "releasedOn": "Aug 12, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b87367417b2b2512b43",
- "title": "Use Arrow Functions to Write Concise Anonymous Functions",
- "description": [
- "In JavaScript, we often don't need to name our functions, especially when passing a function as an argument to another function. Instead, we create inline functions. We don't need to name these functions because we do not reuse them anywhere else.",
- "To achieve this, we often use the following syntax:",
- "const myFunc = function() {
",
- "ES6 provides us with the syntactic sugar to not have to write anonymous functions this way. Instead, you can use arrow function syntax:",
- "
const myVar = \"value\";
return myVar;
}const myFunc = () => {
",
- "When there is no function body, and only a return value, arrow function syntax allows you to omit the keyword
const myVar = \"value\";
return myVar;
}return
as well as the brackets surrounding the code. This helps simplify smaller functions into one-line statements:",
- "const myFunc= () => \"value\"
",
- "This code will still return value
by default.",
- "
",
- "Rewrite the function assigned to the variable magic
which returns a new Date()
to use arrow function syntax. Also make sure nothing is defined using the keyword var
."
- ],
- "challengeSeed": [
- "var magic = function() {",
- " \"use strict\";",
- " return new Date();",
- "};"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var
keyword.');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+magic/g), 'message: magic
should be a constant variable (by using const
).');",
- "assert(typeof magic === 'function', 'message: magic
is a function
.');",
- "assert(magic().getDate() == new Date().getDate(), 'message: magic()
returns correct date.');",
- "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function
keyword was not used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b88367417b2b2512b44",
- "title": "Write Arrow Functions with Parameters",
- "description": [
- "Just like a normal function, you can pass arguments into arrow functions.",
- "// doubles input value and returns it
",
- "You can pass more than one argument into arrow functions as well.",
- "
const doubler = (item) => item * 2;
",
- "Rewrite the myConcat
function which appends contents of arr2
to arr1
so that the function uses arrow function syntax."
- ],
- "challengeSeed": [
- "var myConcat = function(arr1, arr2) {",
- " \"use strict\";",
- " return arr1.concat(arr2);",
- "};",
- "// test your code",
- "console.log(myConcat([1, 2], [3, 4, 5]));"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var
keyword.');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+myConcat/g), 'message: myConcat
should be a constant variable (by using const
).');",
- "assert(typeof myConcat === 'function', 'message: myConcat
should be a function');",
- "assert(() => { const a = myConcat([1], [2]); return a[0] == 1 && a[1] == 2; }, 'message: myConcat()
returns the correct array
');",
- "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function
keyword was not used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b88367417b2b2512b45",
- "title": "Write Higher Order Arrow Functions",
- "description": [
- "It's time we see how powerful arrow functions are when processing data.",
- "Arrow functions work really well with higher order functions, such as map()
, filter()
, and reduce()
, that take other functions as arguments for processing collections of data.",
- "Read the following code:",
- "FBPosts.filter(function(post) {
",
- "We have written this with
return post.thumbnail !== null && post.shares > 100 && post.likes > 500;
})filter()
to at least make it somewhat readable. Now compare it to the following code which uses arrow function syntax instead:",
- "FBPosts.filter((post) => post.thumbnail !== null && post.shares > 100 && post.likes > 500)
",
- "This code is more succinct and accomplishes the same task with fewer lines of code.",
- "
",
- "Use arrow function syntax to compute the square of only the positive integers (fractions are not integers) in the array realNumberArray
and store the new array in the variable squaredIntegers
."
- ],
- "challengeSeed": [
- "const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34];",
- "const squareList = (arr) => {",
- " \"use strict\";",
- " // change code below this line",
- " const squaredIntegers = arr;",
- " // change code above this line",
- " return squaredIntegers;",
- "};",
- "// test your code",
- "const squaredIntegers = squareList(realNumberArray);",
- "console.log(squaredIntegers);"
- ],
- "tests": [
- "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var
keyword.');",
- "getUserInput => assert(getUserInput('index').match(/const\\s+squaredIntegers/g), 'message: squaredIntegers
should be a constant variable (by using const
).');",
- "assert(Array.isArray(squaredIntegers), 'message: squaredIntegers
should be an array
');",
- "assert(squaredIntegers[0] === 16 && squaredIntegers[1] === 1764 && squaredIntegers[2] === 36, 'message: squaredIntegers
should be [16, 1764, 36]
');",
- "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function
keyword was not used.');",
- "getUserInput => assert(!getUserInput('index').match(/(for)|(while)/g), 'message: loop should not be used');",
- "getUserInput => assert(getUserInput('index').match(/map|filter|reduce/g), 'message: map
, filter
, or reduce
should be used');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b88367417b2b2512b46",
- "title": "Set Default Parameters for Your Functions",
- "description": [
- "In order to help us create more flexible functions, ES6 introduces default parameters for functions.",
- "Check out this code:",
- "function greeting(name = \"Anonymous\") {
",
- "The default parameter kicks in when the argument is not specified (it is undefined). As you can see in the example above, the parameter
return \"Hello \" + name;
}
console.log(greeting(\"John\")); // Hello John
console.log(greeting()); // Hello Anonymousname
will receive its default value \"Anonymous\"
when you do not provide a value for the parameter. You can add default values for as many parameters as you want.",
- "
",
- "Modify the function increment
by adding default parameters so that it will add 1 to number
if value
is not specified."
- ],
- "challengeSeed": [
- "const increment = (function() {",
- " \"use strict\";",
- " return function increment(number, value) {",
- " return number + value;",
- " };",
- "})();",
- "console.log(increment(5, 2)); // returns 7",
- "console.log(increment(5)); // returns NaN"
- ],
- "tests": [
- "assert(increment(5, 2) === 7, 'message: The result of increment(5, 2)
should be 7
.');",
- "assert(increment(5) === 6, 'message: The result of increment(5)
should be 6
.');",
- "getUserInput => assert(getUserInput('index').match(/value\\s*=\\s*1/g), 'message: default parameter 1
was used for value
.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b88367417b2b2512b47",
- "title": "Use the Rest Operator with Function Parameters",
- "description": [
- "In order to help us create more flexible functions, ES6 introduces the rest operator for function parameters. With the rest operator, you can create functions that take a variable number of arguments. These arguments are stored in an array that can be accessed later from inside the function.",
- "Check out this code:",
- "function howMany(...args) {
",
- "The rest operator eliminates the need to check the
return \"You have passed \" + args.length + \" arguments.\";
}
console.log(howMany(0, 1, 2)); // You have passed 3 arguments
console.log(howMany(\"string\", null, [1, 2, 3], { })); // You have passed 4 arguments.args
array and allows us to apply map()
, filter()
and reduce()
on the parameters array.",
- "
",
- "Modify the function sum
so that is uses the rest operator and it works in the same way with any number of parameters."
- ],
- "challengeSeed": [
- "const sum = (function() {",
- " \"use strict\";",
- " return function sum(x, y, z) {",
- " const args = [ x, y, z ];",
- " return args.reduce((a, b) => a + b, 0);",
- " };",
- "})();",
- "console.log(sum(1, 2, 3)); // 6"
- ],
- "tests": [
- "assert(sum(0,1,2) === 3, 'message: The result of sum(0,1,2)
should be 3');",
- "assert(sum(1,2,3,4) === 10, 'message: The result of sum(1,2,3,4)
should be 10');",
- "assert(sum(5) === 5, 'message: The result of sum(5)
should be 5');",
- "assert(sum() === 0, 'message: The result of sum()
should be 0');",
- "getUserInput => assert(getUserInput('index').match(/function\\s+sum\\s*\\(\\s*...args\\s*\\)\\s*{/g), 'message: The sum
function uses the ...
spread operator on the args
parameter.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b89367417b2b2512b48",
- "title": "Use the Spread Operator to Evaluate Arrays In-Place",
- "description": [
- "ES6 introduces the spread operator, which allows us to expand arrays and other expressions in places where multiple parameters or elements are expected.",
- "The ES5 code below uses apply()
to compute the maximum value in an array:",
- "var arr = [6, 89, 3, 45];
",
- "We had to use
var maximus = Math.max.apply(null, arr); // returns 89Math.max.apply(null, arr)
because Math.max(arr)
returns NaN
. Math.max()
expects comma-separated arguments, but not an array.",
- "The spread operator makes this syntax much better to read and maintain.",
- "const arr = [6, 89, 3, 45];
",
- "
const maximus = Math.max(...arr); // returns 89...arr
returns an unpacked array. In other words, it spreads the array.",
- "However, the spread operator only works in-place, like in an argument to a function or in an array literal. The following code will not work:",
- "const spreaded = ...arr; // will throw a syntax error
",
- "
",
- "Copy all contents of arr1
into another array arr2
using the spread operator."
- ],
- "challengeSeed": [
- "const arr1 = ['JAN', 'FEB', 'MAR', 'APR', 'MAY'];",
- "let arr2;",
- "(function() {",
- " \"use strict\";",
- " arr2 = []; // change this line",
- "})();",
- "console.log(arr2);"
- ],
- "tests": [
- "assert(arr2.every((v, i) => v === arr1[i]), 'message: arr2
is correct copy of arr1
.');",
- "getUserInput => assert(getUserInput('index').match(/\\[\\s*...arr1\\s*\\]/g),'message: ...
spread operator was used to duplicate arr1
.');",
- "assert((arr1, arr2) => {arr1.push('JUN'); return arr2.length < arr1.length},'message: arr2
remains unchanged when arr1
is changed.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b89367417b2b2512b49",
- "title": "Use Destructuring Assignment to Assign Variables from Objects",
- "description": [
- "We saw earlier how spread operator can effectively spread, or unpack, the contents of the array.",
- "We can do something similar with objects as well. Destructuring assignment is special syntax for neatly assigning values taken directly from an object to variables.",
- "Consider the following ES5 code:",
- "var voxel = {x: 3.6, y: 7.4, z: 6.54 };
",
- "Here's the same assignment statement with ES6 destructuring syntax:",
- "
var x = voxel.x; // x = 3.6
var y = voxel.y; // y = 7.4
var z = voxel.z; // z = 6.54const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54
",
- "If instead you want to store the values of voxel.x
into a
, voxel.y
into b
, and voxel.z
into c
, you have that freedom as well.",
- "const { x : a, y : b, z : c } = voxel // a = 3.6, b = 7.4, c = 6.54
",
- "You may read it as \"get the field x
and copy the value into a
,\" and so on.",
- "
",
- "Use destructuring to obtain the length of the input string str
, and assign the length to len
in line."
- ],
- "challengeSeed": [
- "function getLength(str) {",
- " \"use strict\";",
- "",
- " // change code below this line",
- " const length = 0; // change this",
- " // change code above this line",
- "",
- " return len; // you must assign length to len in line",
- "",
- "}",
- "",
- "console.log(getLength('FreeCodeCamp'));"
- ],
- "tests": [
- "assert(typeof getLength('') === 'number', 'message: the function getLength()
returns a number.');",
- "assert(getLength(\"FreeCodeCamp\") === 12, 'message: getLength(\"FreeCodeCamp\")
should be 12
');",
- "getUserInput => assert(getUserInput('index').match(/\\{\\s*length\\s*:\\s*len\\s*}\\s*=\\s*str/g),'message: destructuring with reassignment was used');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b89367417b2b2512b4a",
- "title": "Use Destructuring Assignment to Assign Variables from Nested Objects",
- "description": [
- "We can similarly destructure nested objects into variables.",
- "Consider the following code:",
- "const a = {
",
- "In the example above, the variable
start: { x: 5, y: 6},
end: { x: 6, y: -9 }
};
const { start : { x: startX, y: startY }} = a;
console.log(startX, startY); // 5, 6start
is assigned the value of a.start
, which is also an object.",
- "
",
- "Use destructuring assignment to obtain max
of forecast.tomorrow
and assign it to maxOfTomorrow
."
- ],
- "challengeSeed": [
- "const LOCAL_FORECAST = {",
- " today: { min: 72, max: 83 },",
- " tomorrow: { min: 73.3, max: 84.6 }",
- "};",
- "",
- "function getMaxOfTmrw(forecast) {",
- " \"use strict\";",
- " // change code below this line",
- " const maxOfTomorrow = undefined; // change this line",
- " // change code above this line",
- " return maxOfTomorrow;",
- "}",
- "",
- "console.log(getMaxOfTmrw(LOCAL_FORECAST)); // should be 84.6"
- ],
- "tests": [
- "assert(getMaxOfTmrw(LOCAL_FORECAST) === 84.6, 'message: maxOfTomorrow
equals 84.6
');",
- "getUserInput => assert(getUserInput('index').match(/\\{\\s*tomorrow\\s*:\\s*\\{\\s*max\\s*:\\s*maxOfTomorrow\\s*\\}\\s*\\}\\s*=\\s*forecast/g),'message: nested destructuring was used');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b89367417b2b2512b4b",
- "title": "Use Destructuring Assignment to Assign Variables from Arrays",
- "description": [
- "ES6 makes destructuring arrays as easy as destructuring objects.",
- "One key difference between the spread operator and array destructuring is that the spread operator unpacks all contents of an array into a comma-separated list. Consequently, you cannot pick or choose which elements you want to assign to variables.",
- "Destructuring an array lets us do exactly that:",
- "const [a, b] = [1, 2, 3, 4, 5, 6];
",
- "The variable
console.log(a, b); // 1, 2a
is assigned the first value of the array, and b
is assigned the second value of the array.",
- "We can also access the value at any index in an array with destructuring by using commas to reach the desired index:",
- "const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
",
- "
console.log(a, b, c); // 1, 2, 5
",
- "Use destructuring assignment to swap the values of a
and b
so that a
receives the value stored in b
, and b
receives the value stored in a
."
- ],
- "challengeSeed": [
- "let a = 8, b = 6;",
- "(() => {",
- " \"use strict\";",
- " // change code below this line",
- " ",
- " // change code above this line",
- "})();",
- "console.log(a); // should be 6",
- "console.log(b); // should be 8"
- ],
- "tests": [
- "assert(a === 6, 'message: Value of a
should be 6, after swapping.');",
- "assert(b === 8, 'message: Value of b
should be 8, after swapping.');",
- "// assert(/\\[\\s*(\\w)\\s*,\\s*(\\w)\\s*\\]\\s*=\\s*\\[\\s*\\2\\s*,\\s*\\1\\s*\\]/g.test(code), 'message: Use array destructuring to swap a and b.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8a367417b2b2512b4c",
- "title": "Use Destructuring Assignment with the Rest Operator to Reassign Array Elements",
- "description": [
- "In some situations involving array destructuring, we might want to collect the rest of the elements into a separate array.",
- "The result is similar to Array.prototype.slice()
, as shown below:",
- "const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
",
- "Variables
console.log(a, b); // 1, 2
console.log(arr); // [3, 4, 5, 7]a
and b
take the first and second values from the array. After that, because of rest operator's presence, arr
gets rest of the values in the form of an array.",
- "The rest element only works correctly as the last variable in the list. As in, you cannot use the rest operator to catch a subarray that leaves out last element of the original array.",
- "
",
- "Use destructuring assignment with the rest operator to perform an effective Array.prototype.slice()
so that arr
is a sub-array of the original array source
with the first two elements ommitted."
- ],
- "challengeSeed": [
- "const source = [1,2,3,4,5,6,7,8,9,10];",
- "function removeFirstTwo(list) {",
- " \"use strict\";",
- " // change code below this line",
- " arr = list; // change this",
- " // change code below this line",
- " return arr;",
- "}",
- "const arr = removeFirstTwo(source);",
- "console.log(arr); // should be [3,4,5,6,7,8,9,10]",
- "console.log(source); // should be [1,2,3,4,5,6,7,8,9,10];"
- ],
- "tests": [
- "assert(arr.every((v, i) => v === i + 3),'message: arr
should be [3,4,5,6,7,8,9,10]
');",
- "getUserInput => assert(getUserInput('index').match(/\\[\\s*\\w\\s*,\\s*\\w\\s*,\\s*...arr\\s*\\]/g),'message: destructuring was used.');",
- "getUserInput => assert(!getUserInput('index').match(/Array.slice/g), 'message: Array.slice()
was not used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8a367417b2b2512b4d",
- "title": "Use Destructuring Assignment to Pass an Object as a Function's Parameters",
- "description": [
- "In some cases, you can destructure the object in a function argument itself.",
- "Consider the code below:",
- "const profileUpdate = (profileData) => {
",
- "This effectively destructures the object sent into the function. This can also be done in-place:",
- "
const { name, age, nationality, location } = profileData;
// do something with these variables
}const profileUpdate = ({ name, age, nationality, location }) => {
",
- "This removes some extra lines and makes our code look neat.",
- "This has the added benefit of not having to manipulate an entire object in a function; only the fields that are needed are copied inside the function.",
- "
/* do something with these fields */
}
",
- "Use destructuring assignment within the argument to the function half
to send only max
and min
inside the function."
- ],
- "challengeSeed": [
- "const stats = {",
- " max: 56.78,",
- " standard_deviation: 4.34,",
- " median: 34.54,",
- " mode: 23.87,",
- " min: -0.75,",
- " average: 35.85",
- "};",
- "const half = (function() {",
- " \"use strict\"; // do not change this line",
- "",
- " // change code below this line",
- " return function half(stats) {",
- " // use function argument destructuring",
- " return (stats.max + stats.min) / 2.0;",
- " };",
- " // change code above this line",
- "",
- "})();",
- "console.log(stats); // should be object",
- "console.log(half(stats)); // should be 28.015"
- ],
- "tests": [
- "assert(typeof stats === 'object', 'message: stats
should be an object
.');",
- "assert(half(stats) === 28.015, 'message: half(stats)
should be 28.015
');",
- "getUserInput => assert(getUserInput('index').match(/\\(\\s*\\{\\s*\\w+\\s*,\\s*\\w+\\s*\\}\\s*\\)/g), 'message: Destructuring was used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8a367417b2b2512b4e",
- "title": "Create Strings using Template Literals",
- "description": [
- "A new feature of ES6 is the template literal. This is a special type of string that allows you to use string interpolation features to create strings.",
- "Consider the code below:",
- "const person = {
",
- "A lot of things happened there.",
- "Firstly, the
name: \"Zodiac Hasbro\",
age: 56
};
// string interpolation
const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;
console.log(greeting); // prints
// Hello, my name is Zodiac Hasbro!
// I am 56 years old.${variable}
syntax used above is a place holder. Basically, you won't have to use concatenation with the +
operator anymore. To add variables to strings, you just drop the variable in a template string and wrap it with ${
and }
.",
- "Secondly, the example uses backticks (`
), not quotes ('
or \"
), to wrap the string. Notice that the string is multi-line.",
- "This new way of creating strings gives you more flexibility to create robust strings.",
- "
",
- "Use template literal syntax with backticks to display each entry of the result
object's failure
array. Each entry should be wrapped inside an li
element with the class attribute text-warning
, and listed within the resultDisplayArray
."
- ],
- "challengeSeed": [
- "const result = {",
- " success: [\"max-length\", \"no-amd\", \"prefer-arrow-functions\"],",
- " failure: [\"no-var\", \"var-on-top\", \"linebreak\"],",
- " skipped: [\"id-blacklist\", \"no-dup-keys\"]",
- "};",
- "function makeList(arr) {",
- " \"use strict\";",
- "",
- " // change code below this line",
- " const resultDisplayArray = null;",
- " // change code above this line",
- "",
- " return resultDisplayArray;",
- "}",
- "/**",
- " * makeList(result.failure) should return:",
- " * [ resultDisplayArray
is a list containing result failure
messages.');",
- "assert(makeList(result.failure).every((v, i) => v === `resultDisplayArray
is the desired output.');",
- "getUserInput => assert(getUserInput('index').match(/\\`const getMousePosition = (x, y) => ({
",
- "
x: x,
y: y
});getMousePosition
is a simple function that returns an object containing two fields.",
- "ES6 provides the syntactic sugar to eliminate the redundancy of having to write x: x
. You can simply write x
once, and it will be converted tox: x
(or something equivalent) under the hood.",
- "Here is the same function from above rewritten to use this new syntax:",
- "const getMousePosition = (x, y) => ({ x, y });
",
- "
",
- "Use simple fields with object literals to create and return a Person
object."
- ],
- "challengeSeed": [
- "const createPerson = (name, age, gender) => {",
- " \"use strict\";",
- " // change code below this line",
- " return {",
- " name: name,",
- " age: age,",
- " gender: gender",
- " };",
- " // change code above this line",
- "};",
- "console.log(createPerson(\"Zodiac Hasbro\", 56, \"male\")); // returns a proper object"
- ],
- "tests": [
- "assert(() => {const res={name:\"Zodiac Hasbro\",age:56,gender:\"male\"}; const person=createPerson(\"Zodiac Hasbro\", 56, \"male\"); return Object.keys(person).every(k => person[k] === res[k]);}, 'message: the output is {name: \"Zodiac Hasbro\", age: 56, gender: \"male\"}
.');",
- "getUserInput => assert(!getUserInput('index').match(/:/g), 'message: No :
were used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8b367417b2b2512b50",
- "title": "Write Concise Declarative Functions with ES6",
- "description": [
- "When defining functions within objects in ES5, we have to use the keyword function
as follows:",
- "const person = {
",
- "With ES6, You can remove the
name: \"Taylor\",
sayHello: function() {
return `Hello! My name is ${this.name}.`;
}
};function
keyword and colon altogether when defining functions in objects. Here's an example of this syntax:",
- "const person = {
",
- "
name: \"Taylor\",
sayHello() {
return `Hello! My name is ${this.name}.`;
}
};
",
- "Refactor the function setGear
inside the object bicycle
to use the shorthand syntax described above."
- ],
- "challengeSeed": [
- "// change code below this line",
- "const bicycle = {",
- " gear: 2,",
- " setGear: function(newGear) {",
- " \"use strict\";",
- " this.gear = newGear;",
- " }",
- "};",
- "// change code above this line",
- "bicycle.setGear(3);",
- "console.log(bicycle.gear);"
- ],
- "tests": [
- "assert(() => { bicycle.setGear(48); return bicycle.gear === 48 }, 'message: setGear
is a function and changes the gear
variable.');",
- "getUserInput => assert(!getUserInput('index').match(/:\\s*function\\s*\\(\\)/g), 'message: Declarative function was used.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8b367417b2b2512b53",
- "title": "Use class Syntax to Define a Constructor Function",
- "description": [
- "ES6 provides a new syntax to help create objects, using the keyword class.",
- "This is to be noted, that the class
syntax is just a syntax, and not a full-fledged class based implementation of object oriented paradigm, unlike in languages like Java, or Python, or Ruby etc.",
- "In ES5, we usually define a constructor function, and use the new
keyword to instantiate an object.",
- "var SpaceShuttle = function(targetPlanet){
",
- "The class syntax simply replaces the constructor function creation:",
- "
this.targetPlanet = targetPlanet;
}
var zeus = new spaceShuttle('Jupiter');class SpaceShuttle {
",
- "Notice that the
constructor(targetPlanet){
this.targetPlanet = targetPlanet;
}
}
const zeus = new spaceShuttle('Jupiter');class
keyword declares a new function, and a constructor was added, which would be invoked when new
is called - to create a new object.",
- "
",
- "Use class
keyword and write a proper constructor to create the Vegetable
class.",
- "The Vegetable
lets you create a vegetable object, with a property name
, to be passed to constructor."
- ],
- "challengeSeed": [
- "function makeClass() {",
- " \"use strict\";",
- " /* Alter code below this line */",
- "",
- " /* Alter code above this line */",
- " return Vegetable;",
- "}",
- "const Vegetable = makeClass();",
- "const carrot = new Vegetable('carrot');",
- "console.log(carrot.name); // => should be 'carrot'"
- ],
- "tests": [
- "assert(typeof Vegetable === 'function' && typeof Vegetable.constructor === 'function', 'message: Vegetable
should be a class
with a defined constructor
method.');",
- "getUserInput => assert(getUserInput('index').match(/class/g),'message: class
keyword was used.');",
- "assert(() => {const a = new Vegetable(\"apple\"); return typeof a === 'object';},'message: Vegetable
can be instantiated.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8c367417b2b2512b54",
- "title": "Use getters and setters to Control Access to an Object",
- "description": [
- "You can obtain values from an object, and set a value of a property within an object.",
- "These are classically called getters and setters.",
- "Getter functions are meant to simply return (get) the value of an object's private variable to the user without the user directly accessing the private variable.",
- "Setter functions are meant to modify (set) the value of an object's private variable based on the value passed into the setter function. This change could involve calculations, or even overwriting the previous value completely.",
- "class Book {
",
- "Notice the syntax we are using to invoke the getter and setter - as if they are not even functions.",
- "Getters and setters are important, because they hide internal implementation details.",
- "
constructor(author) {
this._author = author;
}
// getter
get writer(){
return this._author;
}
// setter
set writer(updatedAuthor){
this._author = updatedAuthor;
}
}
const lol = new Book('anonymous');
console.log(lol.writer);
lol.writer = 'wut';
console.log(lol.writer);
",
- "Use class
keyword to create a Thermostat class. The constructor accepts Farenheit temperature.",
- "Now create getter
and setter
in the class, to obtain the temperature in Celsius scale.",
- "Remember that C = 5/9 * (F - 32)
and F = C * 9.0 / 5 + 32
, where F is the value of temperature in Fahrenheit scale, and C is the value of the same temperature in Celsius scale",
- "Note",
- "When you implement this, you would be tracking the temperature inside the class in one scale - either Fahrenheit or Celsius.",
- "This is the power of getter or setter - you are creating an API for another user, who would get the correct result, no matter which one you track.",
- "In other words, you are abstracting implementation details from the consumer."
- ],
- "challengeSeed": [
- "function makeClass() {",
- " \"use strict\";",
- " /* Alter code below this line */",
- "",
- " /* Alter code above this line */",
- " return Thermostat;",
- "}",
- "const Thermostat = makeClass();",
- "const thermos = new Thermostat(76); // setting in Farenheit scale",
- "let temp = thermos.temperature; // 24.44 in C",
- "thermos.temperature = 26;",
- "temp = thermos.temperature; // 26 in C"
- ],
- "tests": [
- "assert(typeof Thermostat === 'function' && typeof Thermostat.constructor === 'function','message: Thermostat
should be a class
with a defined constructor
method.');",
- "getUserInput => assert(getUserInput('index').match(/class/g),'message: class
keyword was used.');",
- "assert(() => {const t = new Thermostat(32); return typeof t === 'object' && t.temperature === 0;}, 'message: Thermostat
can be instantiated.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8c367417b2b2512b55",
- "title": "Understand the Differences Between import and require",
- "description": [
- "In the past, the function require()
would be used to import the functions and code in external files and modules. While handy, this presents a problem: some files and modules are rather large, and you may only need certain code from those external resources.",
- "ES6 gives us a very handy tool known as import. With it, we can choose which parts of a module or file to load into a given file, saving time and memory.",
- "Consider the following example. Imagine that math_array_functions
has about 20 functions, but I only need one, countItems
, in my current file. The old require()
approach would force me to bring in all 20 functions. With this new import
syntax, I can bring in just the desired function, like so:",
- "import { countItems } from \"math_array_functions\"
",
- "A description of the above code:",
- "import { function } from \"file_path_goes_here\"
",
- "There are a few ways to write an
// We can also import variables the same way!import
statement, but the above is a very common use-case.",
- "Note
The whitespace surrounding the function inside the curly braces is a best practice - it makes it easier to read the import
statement.",
- "Note
The lessons in this section handle non-browser features. import
, and the statements we introduce in the rest of these lessons, won't work on a browser directly. However, we can use various tools to create code out of this to make it work in browser.",
- "Note
In most cases, the file path requires a ./
before it; otherwise, node will look in the node_modules
directory first trying to load it as a dependencie.",
- "
",
- "Add the appropriate import
statement that will allow the current file to use the capitalizeString
function. The file where this function lives is called \"string_functions\"
, and it is in the same directory as the current file."
- ],
- "head": [
- "window.require = function (str) {",
- "if (str === 'string_functions') {",
- "return {",
- "capitalizeString: str => str.toUpperCase()",
- "}}};"
- ],
- "challengeSeed": [
- "\"use strict\";",
- "capitalizeString(\"hello!\");"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/import\\s+\\{\\s?capitalizeString\\s?\\}\\s+from\\s+\"string_functions\"/g), 'message: valid import
statement');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8c367417b2b2512b56",
- "title": "Use export to Reuse a Code Block",
- "description": [
- "In the previous challenge, you learned about import
and how it can be leveraged to import small amounts of code from large files. In order for this to work, though, we must utilize one of the statements that goes with import
, known as export. When we want some code - a function, or a variable - to be usable in another file, we must export it in order to import it into another file. Like import
, export
is a non-browser feature.",
- "The following is what we refer to as a named export. With this, we can import any code we export into another file with the import
syntax you learned in the last lesson. Here's an example:",
- "const capitalizeString = (string) => {
",
- "Alternatively, if you would like to compact all your
return string.charAt(0).toUpperCase() + string.slice(1);
}
export { capitalizeString } //How to export functions.
export const foo = \"bar\"; //How to export variables.export
statements into one line, you can take this approach:",
- "const capitalizeString = (string) => {
",
- "Either approach is perfectly acceptable.",
- "
return string.charAt(0).toUpperCase() + string.slice(1);
}
const foo = \"bar\";
export { capitalizeString, foo }
",
- "Below are two variables that I want to make available for other files to use. Utilizing the first way I demonstrated export
, export the two variables."
- ],
- "head": [
- "window.exports = function(){};"
- ],
- "challengeSeed": [
- "\"use strict\";",
- "const foo = \"bar\";",
- "const boo = \"far\";"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/export\\s+const\\s+foo\\s+=+\\s\"bar\"/g), 'message: foo
is exported.');",
- "getUserInput => assert(getUserInput('index').match(/export\\s+const\\s+boo\\s+=+\\s\"far\"/g), 'message: bar
is exported.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8c367417b2b2512b57",
- "title": "Use * to Import Everything from a File",
- "description": [
- "Suppose you have a file that you wish to import all of its contents into the current file. This can be done with the import * syntax.",
- "Here's an example where the contents of a file named \"math_functions\"
are imported into a file in the same directory:",
- "import * as myMathModule from \"math_functions\"
",
- "And breaking down that code:",
- "
myMathModule.add(2,3);
myMathModule.subtract(5,3);import * as object_with_name_of_your_choice from \"file_path_goes_here\"
",
- "You may use any name following the
object_with_name_of_your_choice.imported_functionimport * as
portion of the statement. In order to utilize this method, it requires an object that receives the imported values. From here, you will use the dot notation to call your imported values.",
- "
",
- "The code below requires the contents of a file, \"capitalize_strings\"
, found in the same directory as it, imported. Add the appropriate import *
statement to the top of the file, using the object provided."
- ],
- "head": [
- "window.require = function(str) {",
- "if (str === 'capitalize_strings') {",
- "return {",
- "capitalize: str => str.toUpperCase(),",
- "lowercase: str => str.toLowerCase()",
- "}}};"
- ],
- "challengeSeed": [
- "\"use strict\";",
- "myStringModule.capitalize(\"foo\");",
- "myStringModule.lowercase(\"Foo\");"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/import\\s+\\*\\s+as\\s+myStringModule\\s+from\\s+\"capitalize_strings\"/g), 'message: Properly uses import * as
syntax.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8c367417b2b2512b58",
- "title": "Create an Export Fallback with export default",
- "description": [
- "In the export
lesson, you learned about the syntax referred to as a named export. This allowed you to make multiple functions and variables available for use in other files.",
- "There is another export
syntax you need to know, known as export default. Usually you will use this syntax if only one value is being exported from a file. It is also used to create a fallback value for a file or module.",
- "Here is a quick example of export default
:",
- "export default function add(x,y) {
",
- "Note: Since
return x + y;
}export default
is used to declare a fallback value for a module or file, you can only have one value be a default export in each module or file. Additionally, you cannot use export default
with var
, let
, or const
",
- "
",
- "The following function should be the fallback value for the module. Please add the necessary code to do so."
- ],
- "head": [
- "window.exports = function(){};"
- ],
- "challengeSeed": [
- "\"use strict\";",
- "function subtract(x,y) {return x - y;}"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/export\\s+default\\s+function\\s+subtract\\(x,y\\)\\s+{return\\s+x\\s-\\s+y;}/g), 'message: Proper used of export
fallback.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8d367417b2b2512b59",
- "title": "Import a Default Export",
- "description": [
- "In the last challenge, you learned about export default
and its uses. It is important to note that, to import a default export, you need to use a different import
syntax.",
- "In the following example, we have a function, add
, that is the default export of a file, \"math_functions\"
. Here is how to import it:",
- "import add from \"math_functions\";
",
- "The syntax differs in one key place - the imported value,
add(5,4); //Will return 9add
, is not surrounded by curly braces, {}
. Unlike exported values, the primary method of importing a default export is to simply write the value's name after import
.",
- "
",
- "In the following code, please import the default export, subtract
, from the file \"math_functions\"
, found in the same directory as this file."
- ],
- "head": [
- "window.require = function(str) {",
- "if (str === 'math_functions') {",
- "return function(a, b) {",
- "return a - b;",
- "}}};"
- ],
- "challengeSeed": [
- "\"use strict\";",
- "subtract(7,4);"
- ],
- "tests": [
- "getUserInput => assert(getUserInput('index').match(/import\\s+subtract\\s+from\\s+\"math_functions\"/g), 'message: Properly imports export default
method.');"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json
deleted file mode 100644
index 11f5ad3b91..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json
+++ /dev/null
@@ -1,1276 +0,0 @@
-{
- "name": "Functional Programming",
- "order": 8,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7b8d367417b2b2512b5a",
- "title": "Introduction to the Functional Programming Challenges",
- "description": [
- "",
- "",
- "Functional programming is an approach to software development based around the evaluation of functions. Like mathematics, functions in programming map input to output to produce a result. You can combine basic functions in many ways to build more and more complex programs.
Functional programming follows a few core principles:
The functional programming software development approach breaks a program into small, testable parts. This section covers basic functional programming principles in JavaScript.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "",
- "challengeSeed": [],
- "tests": [],
- "type": "Waypoint",
- "challengeType": 7,
- "isRequired": false
- },
- {
- "id": "587d7b8d367417b2b2512b5b",
- "title": "Learn About Functional Programming",
- "description": [
- "Functional programming is a style of programming where solutions are simple, isolated functions, without any side effects outside of the function scope.",
- "INPUT -> PROCESS -> OUTPUT
",
- "Functional programming is about:",
- "1) Isolated functions - there is no dependence on the state of the program, which includes global variables that are subject to change",
- "2) Pure functions - the same input always gives the same output",
- "3) Functions with limited side effects - any changes, or mutations, to the state of the program outside the function are carefully controlled",
- "
",
- "The members of freeCodeCamp happen to love tea.",
- "In the code editor, the prepareTea
and getTea
functions are already defined for you. Call the getTea
function to get 40 cups of tea for the team, and store them in the tea4TeamFCC
variable."
- ],
- "challengeSeed": [
- "/**",
- " * A long process to prepare tea.",
- " * @return {string} A cup of tea.",
- " **/",
- "const prepareTea = () => 'greenTea';",
- "",
- "/**",
- " * Get given number of cups of tea.",
- " * @param {number} numOfCups Number of required cups of tea.",
- " * @return {Arraytea4TeamFCC
variable should hold 40 cups of tea for the team.');",
- "assert(tea4TeamFCC[0] === 'greenTea', 'message: The tea4TeamFCC
variable should hold cups of green tea.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8e367417b2b2512b5c",
- "title": "Understand Functional Programming Terminology",
- "description": [
- "The FCC Team had a mood swing and now wants two types of tea: green tea and black tea. General Fact: Client mood swings are pretty common.",
- "With that information, we'll need to revisit the getTea
function from last challenge to handle various tea requests. We can modify getTea
to accept a function as a parameter to be able to change the type of tea it prepares. This makes getTea
more flexible, and gives the programmer more control when client requests change.",
- "But first, let's cover some functional terminology:",
- "Callbacks
are the functions that are slipped or passed into another function to decide the invocation of that function. You may have seen them passed to other methods, for example in filter
, the callback function tells JavaScript the criteria for how to filter an array.",
- "Functions that can be assigned to a variable, passed into another function, or returned from another function just like any other normal value, are called first class
functions. In JavaScript, all functions are first class
functions.",
- "The functions that take a function as an argument, or return a function as a return value are called higher order
functions.",
- "When the functions are passed in to another function or returned from another function, then those functions which gets passed in or returned can be called a lambda
.",
- "
",
- "Prepare 27 cups of green tea and 13 cups of black tea and store them in tea4GreenTeamFCC
and tea4BlackTeamFCC
variables, respectively. Note that the getTea
function has been modified so it now takes a function as the first argument.",
- "Note: The data (the number of cups of tea) is supplied as the last argument. We'll discuss this more in later lessons."
- ],
- "challengeSeed": [
- "/**",
- " * A long process to prepare green tea.",
- " * @return {string} A cup of green tea.",
- " **/",
- "const prepareGreenTea = () => 'greenTea';",
- "",
- "/**",
- " * A long process to prepare black tea.",
- " * @return {string} A cup of black tea.",
- " **/",
- "const prepareBlackTea = () => 'blackTea';",
- "",
- "/**",
- " * Get given number of cups of tea.",
- " * @param {function():string} prepareTea The type of tea preparing function.",
- " * @param {number} numOfCups Number of required cups of tea.",
- " * @return {Arraytea4GreenTeamFCC
variable should hold 27 cups of green tea for the team.');",
- "assert(tea4GreenTeamFCC[0] === 'greenTea', 'message: The tea4GreenTeamFCC
variable should hold cups of green tea.');",
- "assert(tea4BlackTeamFCC.length === 13, 'message: The tea4BlackTeamFCC
variable should hold 13 cups of black tea.');",
- "assert(tea4BlackTeamFCC[0] === 'blackTea', 'message: The tea4BlackTeamFCC
variable should hold cups of black tea.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8e367417b2b2512b5d",
- "title": "Understand the Hazards of Using Imperative Code",
- "description": [
- "Functional programming is a good habit. It keeps your code easy to manage, and saves you from sneaky bugs. But before we get there, let's look at an imperative approach to programming to highlight where you may have issues.",
- "In English (and many other languages), the imperative tense is used to give commands. Similarly, an imperative style in programming is one that gives the computer a set of statements to perform a task.",
- "Often the statements change the state of the program, like updating global variables. A classic example is writing a for
loop that gives exact directions to iterate over the indices of an array.",
- "In contrast, functional programming is a form of declarative programming. You tell the computer what you want done by calling a method or function.",
- "JavaScript offers many predefined methods that handle common tasks so you don't need to write out how the computer should perform them. For example, instead of using the for
loop mentioned above, you could call the map
method which handles the details of iterating over an array. This helps to avoid semantic errors, like the \"Off By One Errors\" that were covered in the Debugging section.",
- "Consider the scenario: you are browsing the web in your browser, and want to track the tabs you have opened. Let's try to model this using some simple object-oriented code.",
- "A Window object is made up of tabs, and you usually have more than one Window open. The titles of each open site in each Window object is held in an array. After working in the browser (opening new tabs, merging windows, and closing tabs), you want to print the tabs that are still open. Closed tabs are removed from the array and new tabs (for simplicity) get added to the end of it.",
- "The code editor shows an implementation of this functionality with functions for tabOpen()
, tabClose()
, and join()
. The array tabs
is part of the Window object that stores the name of the open pages.",
- "Instructions
",
- "Run the code in the editor. It's using a method that has side effects in the program, causing incorrect output. The final list of open tabs should be
['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']
but the output will be slightly different.",
- "Work through the code and see if you can figure out the problem, then advance to the next challenge to learn more."
- ],
- "challengeSeed": [
- "// tabs is an array of titles of each site open within the window",
- "var Window = function(tabs) {",
- " this.tabs = tabs; // we keep a record of the array inside the object",
- "};",
- "",
- "// When you join two windows into one window",
- "Window.prototype.join = function (otherWindow) {",
- " this.tabs = this.tabs.concat(otherWindow.tabs);",
- " return this;",
- "};",
- "",
- "// When you open a new tab at the end",
- "Window.prototype.tabOpen = function (tab) {",
- " this.tabs.push('new tab'); // let's open a new tab for now",
- " return this;",
- "};",
- "",
- "// When you close a tab",
- "Window.prototype.tabClose = function (index) {",
- " var tabsBeforeIndex = this.tabs.splice(0, index); // get the tabs before the tab",
- " var tabsAfterIndex = this.tabs.splice(index); // get the tabs after the tab",
- "",
- " this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // join them together ",
- " return this;",
- " };",
- "",
- "// Let's create three browser windows",
- "var workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // Your mailbox, drive, and other work sites",
- "var socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // Social sites",
- "var videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // Entertainment sites",
- "",
- "// Now perform the tab opening, closing, and other operations",
- "var finalTabs = socialWindow",
- " .tabOpen() // Open a new tab for cat memes",
- " .join(videoWindow.tabClose(2)) // Close third tab in video window, and join",
- " .join(workWindow.tabClose(1).tabOpen());",
- "",
- "alert(finalTabs.tabs);"
- ],
- "tests": [
- "assert(true, 'message: Move ahead to understand the error.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8e367417b2b2512b5e",
- "title": "Avoid Mutations and Side Effects Using Functional Programming",
- "description": [
- "If you haven't already figured it out, the issue in the previous challenge was with the splice
call in the tabClose()
function. Unfortunately, splice
changes the original array it is called on, so the second call to it used a modified array, and gave unexpected results.",
- "This is a small example of a much larger pattern - you call a function on a variable, array, or an object, and the function changes the variable or something in the object.",
- "One of the core principle of functional programming is to not change things. Changes lead to bugs. It's easier to prevent bugs knowing that your functions don't change anything, including the function arguments or any global variable.",
- "The previous example didn't have any complicated operations but the splice
method changed the original array, and resulted in a bug.",
- "Recall that in functional programming, changing or altering things is called mutation
, and the outcome is called a side effect
. A function, ideally, should be a pure function
, meaning that it does not cause any side effects.",
- "Let's try to master this discipline and not alter any variable or object in our code.",
- "
",
- "Fill in the code for the function incrementer
so it returns the value of the global variable fixedValue
increased by one."
- ],
- "challengeSeed": [
- "// the global variable",
- "var fixedValue = 4;",
- "",
- "function incrementer () {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "",
- "var newValue = incrementer(); // Should equal 5",
- "console.log(fixedValue); // Should print 4"
- ],
- "tests": [
- "assert(fixedValue === 4, 'message: Your function incrementer
should not change the value of fixedValue
.');",
- "assert(newValue === 5, 'message: Your incrementer
function should return a value that is one larger than the fixedValue
value.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8e367417b2b2512b5f",
- "title": "Pass Arguments to Avoid External Dependence in a Function",
- "description": [
- "The last challenge was a step closer to functional programming principles, but there is still something missing.",
- "We didn't alter the global variable value, but the function incrementer
would not work without the global variable fixedValue
being there.",
- "Another principle of functional programming is to always declare your dependencies explicitly. This means if a function depends on a variable or object being present, then pass that variable or object directly into the function as an argument.",
- "There are several good consequences from this principle. The function is easier to test, you know exactly what input it takes, and it won't depend on anything else in your program.",
- "This can give you more confidence when you alter, remove, or add new code. You would know what you can or cannot change and you can see where the potential traps are.",
- "Finally, the function would always produce the same output for the same set of inputs, no matter what part of the code executes it.",
- "
",
- "Let's update the incrementer
function to clearly declare its dependencies.",
- "Write the incrementer
function so it takes an argument, and then increases the value by one."
- ],
- "challengeSeed": [
- "// the global variable",
- "var fixedValue = 4;",
- "",
- "// Add your code below this line",
- "function incrementer () {",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "",
- "var newValue = incrementer(fixedValue); // Should equal 5",
- "console.log(fixedValue); // Should print 4"
- ],
- "tests": [
- "assert(fixedValue === 4, 'message: Your function incrementer
should not change the value of fixedValue
.');",
- "assert(code.match(/function\\s+?incrementer\\s*?\\(.+?\\)/g), 'message: Your incrementer
function should take a parameter.');",
- "assert(newValue === 5, 'message: Your incrementer
function should return a value that is one larger than the fixedValue
value.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8f367417b2b2512b60",
- "title": "Refactor Global Variables Out of Functions",
- "description": [
- "So far, we have seen two distinct principles for functional programming:",
- "1) Don't alter a variable or object - create new variables and objects and return them if need be from a function.",
- "2) Declare function arguments - any computation inside a function depends only on the arguments, and not on any global object or variable.",
- "Adding one to a number is not very exciting, but we can apply these principles when working with arrays or more complex objects.",
- "
",
- "Refactor (rewrite) the code so the global array bookList
is not changed inside either function. The add
function should add the given bookName
to the end of an array. The remove
function should remove the given bookName
from an array. Both functions should return an array, and any new parameters should be added before the bookName
one."
- ],
- "challengeSeed": [
- "// the global variable",
- "var bookList = [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"];",
- "",
- "/* This function should add a book to the list and return the list */",
- "// New parameters should come before the bookName one",
- "",
- "// Add your code below this line",
- "function add (bookName) {",
- " ",
- " return bookList.push(bookName);",
- " ",
- " // Add your code above this line",
- "}",
- "",
- "/* This function should remove a book from the list and return the list */",
- "// New parameters should come before the bookName one",
- "",
- "// Add your code below this line",
- "function remove (bookName) {",
- " if (bookList.indexOf(bookName) >= 0) {",
- " ",
- " return bookList.splice(0, 1, bookName);",
- " ",
- " // Add your code above this line",
- " }",
- "}",
- "",
- "var newBookList = add(bookList, 'A Brief History of Time');",
- "var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');",
- "var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');",
- "",
- "console.log(bookList);"
- ],
- "tests": [
- "assert(JSON.stringify(bookList) === JSON.stringify([\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"]), 'message: bookList
should not change and still equal [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"]
.');",
- "assert(JSON.stringify(newBookList) === JSON.stringify(['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']), 'message: newBookList
should equal [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\", \"A Brief History of Time\"]
.');",
- "assert(JSON.stringify(newerBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']), 'message: newerBookList
should equal [\"The Hound of the Baskervilles\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"]
.');",
- "assert(JSON.stringify(newestBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']), 'message: newestBookList
should equal [\"The Hound of the Baskervilles\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\", \"A Brief History of Time\"]
.');"
- ],
- "solutions": [],
- "hints": [
- "Look at how the functions are called to see the correct order of the parameters.",
- "Consider using the concat method instead of push.",
- "The slice method returns a new array without modifying the original."
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8f367417b2b2512b61",
- "title": "Use the map Method to Extract Data from an Array",
- "description": [
- "So far we have learned to use pure functions to avoid side effects in a program. Also, we have seen the value in having a function only depend on its input arguments.",
- "This is only the beginning. As its name suggests, functional programming is centered around a theory of functions.",
- "It would make sense to be able to pass them as arguments to other functions, and return a function from another function. Functions are considered First Class Objects
in JavaScript, which means they can be used like any other object. They can be saved in variables, stored in an object, or passed as function arguments.",
- "Let's start with some simple array functions, which are methods on the array object prototype. In this exercise we are looking at Array.prototype.map()
, or more simply map
.",
- "Remember that the map
method is a way to iterate over each item in an array. It creates a new array (without changing the original one) after applying a callback function to every element.",
- "
",
- "The watchList
array holds objects with information on several movies. Use map
to pull the title and rating from watchList
and save the new array in the rating
variable. The code in the editor currently uses a for
loop to do this, replace the loop functionality with your map
expression."
- ],
- "challengeSeed": [
- "// the global variable",
- "var watchList = [",
- " { ",
- " \"Title\": \"Inception\",",
- " \"Year\": \"2010\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"16 Jul 2010\",",
- " \"Runtime\": \"148 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Christopher Nolan\",",
- " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",",
- " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",",
- " \"Language\": \"English, Japanese, French\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.8\",",
- " \"imdbVotes\": \"1,446,708\",",
- " \"imdbID\": \"tt1375666\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Interstellar\",",
- " \"Year\": \"2014\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"07 Nov 2014\",",
- " \"Runtime\": \"169 min\",",
- " \"Genre\": \"Adventure, Drama, Sci-Fi\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",",
- " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",",
- " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",",
- " \"Language\": \"English\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.6\",",
- " \"imdbVotes\": \"910,366\",",
- " \"imdbID\": \"tt0816692\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"The Dark Knight\",",
- " \"Year\": \"2008\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Jul 2008\",",
- " \"Runtime\": \"152 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",",
- " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",",
- " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",",
- " \"Language\": \"English, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"82\",",
- " \"imdbRating\": \"9.0\",",
- " \"imdbVotes\": \"1,652,832\",",
- " \"imdbID\": \"tt0468569\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Batman Begins\",",
- " \"Year\": \"2005\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"15 Jun 2005\",",
- " \"Runtime\": \"140 min\",",
- " \"Genre\": \"Action, Adventure\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",",
- " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",",
- " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",",
- " \"Language\": \"English, Urdu, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",",
- " \"Metascore\": \"70\",",
- " \"imdbRating\": \"8.3\",",
- " \"imdbVotes\": \"972,584\",",
- " \"imdbID\": \"tt0372784\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"Avatar\",",
- " \"Year\": \"2009\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Dec 2009\",",
- " \"Runtime\": \"162 min\",",
- " \"Genre\": \"Action, Adventure, Fantasy\",",
- " \"Director\": \"James Cameron\",",
- " \"Writer\": \"James Cameron\",",
- " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",",
- " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",",
- " \"Language\": \"English, Spanish\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"83\",",
- " \"imdbRating\": \"7.9\",",
- " \"imdbVotes\": \"876,575\",",
- " \"imdbID\": \"tt0499549\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " }",
- "];",
- "",
- "// Add your code below this line",
- "",
- "var rating = [];",
- "for(var i=0; i < watchList.length; i++){",
- " rating.push({title: watchList[i][\"Title\"], rating: watchList[i][\"imdbRating\"]});",
- "}",
- "",
- "// Add your code above this line",
- "",
- "console.log(rating); "
- ],
- "tests": [
- "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList
variable should not change.');",
- "assert(!code.match(/for\\s*?\\(.+?\\)/g), 'message: Your code should not use a for
loop.');",
- "assert(code.match(/\\.map/g), 'message: Your code should use the map
method.');",
- "assert(JSON.stringify(rating) === JSON.stringify([{\"title\":\"Inception\",\"rating\":\"8.8\"},{\"title\":\"Interstellar\",\"rating\":\"8.6\"},{\"title\":\"The Dark Knight\",\"rating\":\"9.0\"},{\"title\":\"Batman Begins\",\"rating\":\"8.3\"},{\"title\":\"Avatar\",\"rating\":\"7.9\"}]), 'message: rating
should equal [{\"title\":\"Inception\",\"rating\":\"8.8\"},{\"title\":\"Interstellar\",\"rating\":\"8.6\"},{\"title\":\"The Dark Knight\",\"rating\":\"9.0\"},{\"title\":\"Batman Begins\",\"rating\":\"8.3\"},{\"title\":\"Avatar\",\"rating\":\"7.9\"}]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8f367417b2b2512b62",
- "title": "Implement map on a Prototype",
- "description": [
- "As you have seen from applying Array.prototype.map()
, or simply map()
earlier, the map
method returns an array of the same length as the one it was called on. It also doesn't alter the original array, as long as its callback function doesn't.",
- "In other words, map
is a pure function, and its output depends solely on its inputs. Plus, it takes another function as its argument.",
- "It would teach us a lot about map
to try to implement a version of it that behaves exactly like the Array.prototype.map()
with a for
loop or Array.prototype.forEach()
.",
- "Note: A pure function is allowed to alter local variables defined within its scope, although, it's preferable to avoid that as well.",
- "
",
- "Write your own Array.prototype.myMap()
, which should behave exactly like Array.prototype.map()
. You may use a for
loop or the forEach
method."
- ],
- "challengeSeed": [
- "// the global Array",
- "var s = [23, 65, 98, 5];",
- "",
- "Array.prototype.myMap = function(callback){",
- " var newArray = [];",
- " // Add your code below this line",
- " ",
- " // Add your code above this line",
- " return newArray;",
- "",
- "};",
- "",
- "var new_s = s.myMap(function(item){",
- " return item * 2;",
- "});"
- ],
- "tests": [
- "assert(JSON.stringify(new_s) === JSON.stringify([46, 130, 196, 10]), 'message: new_s
should equal [46, 130, 196, 10]
.');",
- "assert(!code.match(/\\.map/g), 'message: Your code should not use the map
method.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8f367417b2b2512b63",
- "title": "Use the filter Method to Extract Data from an Array",
- "description": [
- "Another useful array function is Array.prototype.filter()
, or simply filter()
. The filter
method returns a new array which is at most as long as the original array, but usually has fewer items.",
- "Filter
doesn't alter the original array, just like map
. It takes a callback function that applies the logic inside the callback on each element of the array. If an element returns true based on the criteria in the callback function, then it is included in the new array.",
- "
",
- "The variable watchList
holds an array of objects with information on several movies. Use a combination of filter
and map
to return a new array of objects with only title
and rating
keys, but where imdbRating
is greater than or equal to 8.0. Note that the rating values are saved as strings in the object and you may want to convert them into numbers to perform mathematical operations on them."
- ],
- "challengeSeed": [
- "// the global variable",
- "var watchList = [",
- " { ",
- " \"Title\": \"Inception\",",
- " \"Year\": \"2010\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"16 Jul 2010\",",
- " \"Runtime\": \"148 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Christopher Nolan\",",
- " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",",
- " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",",
- " \"Language\": \"English, Japanese, French\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.8\",",
- " \"imdbVotes\": \"1,446,708\",",
- " \"imdbID\": \"tt1375666\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Interstellar\",",
- " \"Year\": \"2014\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"07 Nov 2014\",",
- " \"Runtime\": \"169 min\",",
- " \"Genre\": \"Adventure, Drama, Sci-Fi\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",",
- " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",",
- " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",",
- " \"Language\": \"English\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.6\",",
- " \"imdbVotes\": \"910,366\",",
- " \"imdbID\": \"tt0816692\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"The Dark Knight\",",
- " \"Year\": \"2008\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Jul 2008\",",
- " \"Runtime\": \"152 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",",
- " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",",
- " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",",
- " \"Language\": \"English, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"82\",",
- " \"imdbRating\": \"9.0\",",
- " \"imdbVotes\": \"1,652,832\",",
- " \"imdbID\": \"tt0468569\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Batman Begins\",",
- " \"Year\": \"2005\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"15 Jun 2005\",",
- " \"Runtime\": \"140 min\",",
- " \"Genre\": \"Action, Adventure\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",",
- " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",",
- " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",",
- " \"Language\": \"English, Urdu, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",",
- " \"Metascore\": \"70\",",
- " \"imdbRating\": \"8.3\",",
- " \"imdbVotes\": \"972,584\",",
- " \"imdbID\": \"tt0372784\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"Avatar\",",
- " \"Year\": \"2009\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Dec 2009\",",
- " \"Runtime\": \"162 min\",",
- " \"Genre\": \"Action, Adventure, Fantasy\",",
- " \"Director\": \"James Cameron\",",
- " \"Writer\": \"James Cameron\",",
- " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",",
- " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",",
- " \"Language\": \"English, Spanish\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"83\",",
- " \"imdbRating\": \"7.9\",",
- " \"imdbVotes\": \"876,575\",",
- " \"imdbID\": \"tt0499549\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " }",
- "];",
- "",
- "// Add your code below this line",
- "",
- "var filteredList;",
- "",
- "// Add your code above this line",
- "",
- "console.log(filteredList); "
- ],
- "tests": [
- "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList
variable should not change.');",
- "assert(code.match(/\\.filter/g), 'message: Your code should use the filter
method.');",
- "assert(!code.match(/for\\s*?\\(.+?\\)/g), 'message: Your code should not use a for
loop.');",
- "assert.deepEqual(filteredList, [{\"title\": \"Inception\",\"rating\": \"8.8\"},{\"title\": \"Interstellar\",\"rating\": \"8.6\"},{\"title\": \"The Dark Knight\",\"rating\": \"9.0\"},{\"title\": \"Batman Begins\",\"rating\": \"8.3\"}], 'message: filteredList
should equal [{\"title\": \"Inception\",\"rating\": \"8.8\"},{\"title\": \"Interstellar\",\"rating\": \"8.6\"},{\"title\": \"The Dark Knight\",\"rating\": \"9.0\"},{\"title\": \"Batman Begins\",\"rating\": \"8.3\"}]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b8f367417b2b2512b64",
- "title": "Implement the filter Method on a Prototype",
- "description": [
- "It would teach us a lot about the filter
method if we try to implement a version of it that behaves exactly like Array.prototype.filter()
. It can use either a for
loop or Array.prototype.forEach()
.",
- "Note: A pure function is allowed to alter local variables defined within its scope, although, it's preferable to avoid that as well.",
- "
",
- "Write your own Array.prototype.myFilter()
, which should behave exactly like Array.prototype.filter()
. You may use a for
loop or the Array.prototype.forEach()
method."
- ],
- "challengeSeed": [
- "// the global Array",
- "var s = [23, 65, 98, 5];",
- "",
- "Array.prototype.myFilter = function(callback){",
- " var newArray = [];",
- " // Add your code below this line",
- " ",
- " // Add your code above this line",
- " return newArray;",
- "",
- "};",
- "",
- "var new_s = s.myFilter(function(item){",
- " return item % 2 === 1;",
- "});"
- ],
- "tests": [
- "assert(JSON.stringify(new_s) === JSON.stringify([23, 65, 5]), 'message: new_s
should equal [23, 65, 5]
.');",
- "assert(!code.match(/\\.filter/g), 'message: Your code should not use the filter
method.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7b90367417b2b2512b65",
- "title": "Return Part of an Array Using the slice Method",
- "description": [
- "The slice
method returns a copy of certain elements of an array. It can take two arguments, the first gives the index of where to begin the slice, the second is the index for where to end the slice (and it's non-inclusive). If the arguments are not provided, the default is to start at the beginning of the array through the end, which is an easy way to make a copy of the entire array. The slice
method does not mutate the original array, but returns a new one.",
- "Here's an example:",
- "var arr = [\"Cat\", \"Dog\", \"Tiger\", \"Zebra\"];
",
- "
var newArray = arr.slice(1, 3);
// Sets newArray to [\"Dog\", \"Tiger\"]
",
- "Use the slice
method in the sliceArray
function to return part of the anim
array given the provided beginSlice
and endSlice
indices. The function should return an array."
- ],
- "challengeSeed": [
- "function sliceArray(anim, beginSlice, endSlice) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "var inputAnim = [\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"];",
- "sliceArray(inputAnim, 1, 3);"
- ],
- "tests": [
- "assert(code.match(/\\.slice/g), 'message: Your code should use the slice
method.');",
- "assert(JSON.stringify(inputAnim) === JSON.stringify([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"]), 'message: The inputAnim
variable should not change.');",
- "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 3)) === JSON.stringify([\"Dog\", \"Tiger\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 3)
should return [\"Dog\", \"Tiger\"]
.');",
- "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 0, 1)) === JSON.stringify([\"Cat\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 0, 1)
should return [\"Cat\"]
.');",
- "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 4)) === JSON.stringify([\"Dog\", \"Tiger\", \"Zebra\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 4)
should return [\"Dog\", \"Tiger\", \"Zebra\"]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "9d7123c8c441eeafaeb5bdef",
- "title": "Remove Elements from an Array Using slice Instead of splice",
- "description": [
- "A common pattern while working with arrays is when you want to remove items and keep the rest of the array. JavaScript offers the splice
method for this, which takes arguments for the index of where to start removing items, then the number of items to remove. If the second argument is not provided, the default is to remove items through the end. However, the splice
method mutates the original array it is called on. Here's an example:",
- "var cities = [\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"];
",
- "As we saw in the last challenge, the
cities.splice(3, 1); // Returns \"London\" and deletes it from the cities array
// cities is now [\"Chicago\", \"Delhi\", \"Islamabad\", \"Berlin\"]slice
method does not mutate the original array, but returns a new one which can be saved into a variable. Recall that the slice
method takes two arguments for the indices to begin and end the slice (the end is non-inclusive), and returns those items in a new array. Using the slice
method instead of splice
helps to avoid any array-mutating side effects.",
- "
",
- "Rewrite the function nonMutatingSplice
by using slice
instead of splice
. It should limit the provided cities
array to a length of 3, and return a new array with only the first three items.",
- "Do not mutate the original array provided to the function."
- ],
- "challengeSeed": [
- "function nonMutatingSplice(cities) {",
- " // Add your code below this line",
- " return cities.splice(3);",
- " ",
- " // Add your code above this line",
- "}",
- "var inputCities = [\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"];",
- "nonMutatingSplice(inputCities);"
- ],
- "tests": [
- "assert(code.match(/\\.slice/g), 'message: Your code should use the slice
method.');",
- "assert(!code.match(/\\.splice/g), 'message: Your code should not use the splice
method.');",
- "assert(JSON.stringify(inputCities) === JSON.stringify([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"]), 'message: The inputCities
array should not change.');",
- "assert(JSON.stringify(nonMutatingSplice([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"])) === JSON.stringify([\"Chicago\", \"Delhi\", \"Islamabad\"]), 'message: nonMutatingSplice([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"])
should return [\"Chicago\", \"Delhi\", \"Islamabad\"]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7da9367417b2b2512b66",
- "title": "Combine Two Arrays Using the concat Method",
- "description": [
- "Concatenation
means to join items end to end. JavaScript offers the concat
method for both strings and arrays that work in the same way. For arrays, the method is called on one, then another array is provided as the argument to concat
, which is added to the end of the first array. It returns a new array and does not mutate either of the original arrays. Here's an example:",
- "[1, 2, 3].concat([4, 5, 6]);
",
- "
// Returns a new array [1, 2, 3, 4, 5, 6]
",
- "Use the concat
method in the nonMutatingConcat
function to concatenate attach
to the end of original
. The function should return the concatenated array."
- ],
- "challengeSeed": [
- "function nonMutatingConcat(original, attach) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "var first = [1, 2, 3];",
- "var second = [4, 5];",
- "nonMutatingConcat(first, second);"
- ],
- "tests": [
- "assert(code.match(/\\.concat/g), 'message: Your code should use the concat
method.');",
- "assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]), 'message: The first
array should not change.');",
- "assert(JSON.stringify(second) === JSON.stringify([4, 5]), 'message: The second
array should not change.');",
- "assert(JSON.stringify(nonMutatingConcat([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]), 'message: nonMutatingConcat([1, 2, 3], [4, 5])
should return [1, 2, 3, 4, 5]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7da9367417b2b2512b67",
- "title": "Add Elements to the End of an Array Using concat Instead of push",
- "description": [
- "Functional programming is all about creating and using non-mutating functions.",
- "The last challenge introduced the concat
method as a way to combine arrays into a new one without mutating the original arrays. Compare concat
to the push
method. Push
adds an item to the end of the same array it is called on, which mutates that array. Here's an example:",
- "var arr = [1, 2, 3];
",
- "
arr.push([4, 5, 6]);
// arr is changed to [1, 2, 3, [4, 5, 6]]
// Not the functional programming wayConcat
offers a way to add new items to the end of an array without any mutating side effects.",
- "
",
- "Change the nonMutatingPush
function so it uses concat
to add newItem
to the end of original
instead of push
. The function should return an array."
- ],
- "challengeSeed": [
- "function nonMutatingPush(original, newItem) {",
- " // Add your code below this line",
- " return original.push(newItem);",
- " ",
- " // Add your code above this line",
- "}",
- "var first = [1, 2, 3];",
- "var second = [4, 5];",
- "nonMutatingPush(first, second);"
- ],
- "tests": [
- "assert(code.match(/\\.concat/g), 'message: Your code should use the concat
method.');",
- "assert(!code.match(/\\.push/g), 'message: Your code should not use the push
method.');",
- "assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]), 'message: The first
array should not change.');",
- "assert(JSON.stringify(second) === JSON.stringify([4, 5]), 'message: The second
array should not change.');",
- "assert(JSON.stringify(nonMutatingPush([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]), 'message: nonMutatingPush([1, 2, 3], [4, 5])
should return [1, 2, 3, 4, 5]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7da9367417b2b2512b68",
- "title": "Use the reduce Method to Analyze Data",
- "description": [
- "Array.prototype.reduce()
, or simply reduce()
, is the most general of all array operations in JavaScript. You can solve almost any array processing problem using the reduce
method.",
- "This is not the case with the filter
and map
methods since they do not allow interaction between two different elements of the array. For example, if you want to compare elements of the array, or add them together, filter
or map
could not process that.",
- "The reduce
method allows for more general forms of array processing, and it's possible to show that both filter
and map
can be derived as a special application of reduce
.",
- "However, before we get there, let's practice using reduce
first.",
- "
",
- "The variable watchList
holds an array of objects with information on several movies. Use reduce
to find the average IMDB rating of the movies directed by Christopher Nolan. Recall from prior challenges how to filter
data and map
over it to pull what you need. You may need to create other variables, but save the final average into the variable averageRating
. Note that the rating values are saved as strings in the object and need to be converted into numbers before they are used in any mathematical operations."
- ],
- "challengeSeed": [
- "// the global variable",
- "var watchList = [",
- " { ",
- " \"Title\": \"Inception\",",
- " \"Year\": \"2010\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"16 Jul 2010\",",
- " \"Runtime\": \"148 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Christopher Nolan\",",
- " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",",
- " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",",
- " \"Language\": \"English, Japanese, French\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.8\",",
- " \"imdbVotes\": \"1,446,708\",",
- " \"imdbID\": \"tt1375666\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Interstellar\",",
- " \"Year\": \"2014\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"07 Nov 2014\",",
- " \"Runtime\": \"169 min\",",
- " \"Genre\": \"Adventure, Drama, Sci-Fi\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",",
- " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",",
- " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",",
- " \"Language\": \"English\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",",
- " \"Metascore\": \"74\",",
- " \"imdbRating\": \"8.6\",",
- " \"imdbVotes\": \"910,366\",",
- " \"imdbID\": \"tt0816692\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"The Dark Knight\",",
- " \"Year\": \"2008\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Jul 2008\",",
- " \"Runtime\": \"152 min\",",
- " \"Genre\": \"Action, Adventure, Crime\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",",
- " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",",
- " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",",
- " \"Language\": \"English, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"82\",",
- " \"imdbRating\": \"9.0\",",
- " \"imdbVotes\": \"1,652,832\",",
- " \"imdbID\": \"tt0468569\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " { ",
- " \"Title\": \"Batman Begins\",",
- " \"Year\": \"2005\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"15 Jun 2005\",",
- " \"Runtime\": \"140 min\",",
- " \"Genre\": \"Action, Adventure\",",
- " \"Director\": \"Christopher Nolan\",",
- " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",",
- " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",",
- " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",",
- " \"Language\": \"English, Urdu, Mandarin\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",",
- " \"Metascore\": \"70\",",
- " \"imdbRating\": \"8.3\",",
- " \"imdbVotes\": \"972,584\",",
- " \"imdbID\": \"tt0372784\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " },",
- " {",
- " \"Title\": \"Avatar\",",
- " \"Year\": \"2009\",",
- " \"Rated\": \"PG-13\",",
- " \"Released\": \"18 Dec 2009\",",
- " \"Runtime\": \"162 min\",",
- " \"Genre\": \"Action, Adventure, Fantasy\",",
- " \"Director\": \"James Cameron\",",
- " \"Writer\": \"James Cameron\",",
- " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",",
- " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",",
- " \"Language\": \"English, Spanish\",",
- " \"Country\": \"USA, UK\",",
- " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",",
- " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",",
- " \"Metascore\": \"83\",",
- " \"imdbRating\": \"7.9\",",
- " \"imdbVotes\": \"876,575\",",
- " \"imdbID\": \"tt0499549\",",
- " \"Type\": \"movie\",",
- " \"Response\": \"True\"",
- " }",
- "];",
- "",
- "// Add your code below this line",
- "",
- "var averageRating;",
- "",
- "// Add your code above this line",
- "",
- "console.log(averageRating); "
- ],
- "tests": [
- "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList
variable should not change.');",
- "assert(code.match(/\\.reduce/g), 'message: Your code should use the reduce
method.');",
- "assert(averageRating == 8.675, 'message: The averageRating
should equal 8.675.');",
- "assert(!code.match(/for\\s*?\\(.*\\)/g), 'message: Your code should not use a for
loop.');"
- ],
- "solutions": [],
- "hints": [
- "Try using .filter() to filter the watchList by Director.",
- "Try using .map() to return an array of ratings.",
- "You can use Number() to convert a string into a number."
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7da9367417b2b2512b69",
- "title": "Sort an Array Alphabetically using the sort Method",
- "description": [
- "The sort
method sorts the elements of an array according to the callback function.",
- "For example:",
- "function ascendingOrder(arr) {
",
- "Note: It's encouraged to provide a callback function to specify how to sort the array items. JavaScript's default sorting method is by string Unicode point value, which may return unexpected results.",
- "
return arr.sort(function(a, b) {
return a - b;
});
}
ascendingOrder([1, 5, 2, 3, 4]);
// Returns [1, 2, 3, 4, 5]
function reverseAlpha(arr) {
return arr.sort(function(a, b) {
return a < b;
});
}
reverseAlpha(['l', 'h', 'z', 'b', 's']);
// Returns ['z', 's', 'l', 'h', 'b']
",
- "Use the sort
method in the alphabeticalOrder
function to sort the elements of arr
in alphabetical order."
- ],
- "challengeSeed": [
- "function alphabeticalOrder(arr) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"]);"
- ],
- "tests": [
- "assert(code.match(/\\.sort/g), 'message: Your code should use the sort
method.');",
- "assert(JSON.stringify(alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"])) === JSON.stringify([\"a\", \"a\", \"c\", \"d\", \"g\", \"z\"]), 'message: alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"])
should return [\"a\", \"a\", \"c\", \"d\", \"g\", \"z\"]
.');",
- "assert(JSON.stringify(alphabeticalOrder([\"x\", \"h\", \"a\", \"m\", \"n\", \"m\"])) === JSON.stringify([\"a\", \"h\", \"m\", \"m\", \"n\", \"x\"]), 'message: alphabeticalOrder([\"x\", \"h\", \"a\", \"m\", \"n\", \"m\"])
should return [\"a\", \"h\", \"m\", \"m\", \"n\", \"x\"]
.');",
- "assert(JSON.stringify(alphabeticalOrder([\"a\", \"a\", \"a\", \"a\", \"x\", \"t\"])) === JSON.stringify([\"a\", \"a\", \"a\", \"a\", \"t\", \"x\"]), 'message: alphabeticalOrder([\"a\", \"a\", \"a\", \"a\", \"x\", \"t\"])
should return [\"a\", \"a\", \"a\", \"a\", \"t\", \"x\"]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7da9367417b2b2512b6a",
- "title": "Return a Sorted Array Without Changing the Original Array",
- "description": [
- "A side effect of the sort
method is that it changes the order of the elements in the original array. In other words, it mutates the array in place. One way to avoid this is to first concatenate an empty array to the one being sorted (remember that concat
returns a new array), then run the sort
method.",
- "
",
- "Use the sort
method in the nonMutatingSort
function to sort the elements of an array in ascending order. The function should return a new array, and not mutate the globalArray
variable."
- ],
- "challengeSeed": [
- "var globalArray = [5, 6, 3, 2, 9];",
- "function nonMutatingSort(arr) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "nonMutatingSort(globalArray);"
- ],
- "tests": [
- "assert(code.match(/\\.sort/g), 'message: Your code should use the sort
method.');",
- "assert(code.match(/\\.concat/g), 'message: Your code should use the concat
method.');",
- "assert(JSON.stringify(globalArray) === JSON.stringify([5, 6, 3, 2, 9]), 'message: The globalArray
variable should not change.');",
- "assert(JSON.stringify(nonMutatingSort(globalArray)) === JSON.stringify([2, 3, 5, 6, 9]), 'message: nonMutatingSort(globalArray)
should return [2, 3, 5, 6, 9]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daa367417b2b2512b6b",
- "title": "Split a String into an Array Using the split Method",
- "description": [
- "The split
method splits a string into an array of strings. It takes an argument for the delimiter, which can be a character to use to break up the string or a regular expression. For example, if the delimiter is a space, you get an array of words, and if the delimiter is an empty string, you get an array of each character in the string.",
- "Here are two examples that split one string by spaces, then another by digits using a regular expression:",
- "var str = \"Hello World\";
",
- "Since strings are immutable, the
var bySpace = str.split(\" \");
// Sets bySpace to [\"Hello\", \"World\"]
var otherString = \"How9are7you2today\";
var byDigits = str.split(/\\d/);
// Sets byDigits to [\"How\", \"are\", \"you\", \"today\"]split
method makes it easier to work with them.",
- "
",
- "Use the split
method inside the splitify
function to split str
into an array of words. The function should return the array. Note that the words are not always separated by spaces, and the array should not contain punctuation."
- ],
- "challengeSeed": [
- "function splitify(str) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "splitify(\"Hello World,I-am code\");"
- ],
- "tests": [
- "assert(code.match(/\\.split/g), 'message: Your code should use the split
method.');",
- "assert(JSON.stringify(splitify(\"Hello World,I-am code\")) === JSON.stringify([\"Hello\", \"World\", \"I\", \"am\", \"code\"]), 'message: splitify(\"Hello World,I-am code\")
should return [\"Hello\", \"World\", \"I\", \"am\", \"code\"]
.');",
- "assert(JSON.stringify(splitify(\"Earth-is-our home\")) === JSON.stringify([\"Earth\", \"is\", \"our\", \"home\"]), 'message: splitify(\"Earth-is-our home\")
should return [\"Earth\", \"is\", \"our\", \"home\"]
.');",
- "assert(JSON.stringify(splitify(\"This.is.a-sentence\")) === JSON.stringify([\"This\", \"is\", \"a\", \"sentence\"]), 'message: splitify(\"This.is.a-sentence\")
should return [\"This\", \"is\", \"a\", \"sentence\"]
.');"
- ],
- "solutions": [],
- "hints": [
- "The regex pre-defined character class for non-alphanumerics is \\W."
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daa367417b2b2512b6c",
- "title": "Combine an Array into a String Using the join Method",
- "description": [
- "The join
method is used to join the elements of an array together to create a string. It takes an argument for the delimiter that is used to separate the array elements in the string.",
- "Here's an example:",
- "var arr = [\"Hello\", \"World\"];
",
- "
var str = arr.join(\" \");
// Sets str to \"Hello World\"
",
- "Use the join
method (among others) inside the sentensify
function to make a sentence from the words in the string str
. The function should return a string. For example, \"I-like-Star-Wars\" would be converted to \"I like Star Wars\". For this challenge, do not use the replace
method."
- ],
- "challengeSeed": [
- "function sentensify(str) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "sentensify(\"May-the-force-be-with-you\");"
- ],
- "tests": [
- "assert(code.match(/\\.join/g), 'message: Your code should use the join
method.');",
- "assert(!code.match(/\\.replace/g), 'message: Your code should not use the replace
method.');",
- "assert(typeof sentensify(\"May-the-force-be-with-you\") === \"string\", 'message: sentensify(\"May-the-force-be-with-you\")
should return a string.');",
- "assert(sentensify(\"May-the-force-be-with-you\") === \"May the force be with you\", 'message: sentensify(\"May-the-force-be-with-you\")
should return \"May the force be with you\"
.');",
- "assert(sentensify(\"The.force.is.strong.with.this.one\") === \"The force is strong with this one\", 'message: sentensify(\"The.force.is.strong.with.this.one\")
should return \"The force is strong with this one\"
.');",
- "assert(sentensify(\"There,has,been,an,awakening\") === \"There has been an awakening\", 'message: sentensify(\"There,has,been,an,awakening\")
should return \"There has been an awakening\"
.');"
- ],
- "solutions": [],
- "hints": [
- "First try to split the given string before applying the join method."
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dab367417b2b2512b6d",
- "title": "Apply Functional Programming to Convert Strings to URL Slugs",
- "description": [
- "The last several challenges covered a number of useful array and string methods that follow functional programming principles. We've also learned about reduce
, which is a powerful method used to reduce problems to simpler forms. From computing averages to sorting, any array operation can be achieved by applying it. Recall that map
and filter
are special cases of reduce
.",
- "Let's combine what we've learned to solve a practical problem.",
- "Many content management sites (CMS) have the titles of a post added to part of the URL for simple bookmarking purposes. For example, if you write a Medium post titled \"Stop Using Reduce\", it's likely the URL would have some form of the title string in it (\".../stop-using-reduce\"). You may have already noticed this on the freeCodeCamp site.",
- "
",
- "Fill in the urlSlug
function so it converts a string title
and returns the hyphenated version for the URL. You can use any of the methods covered in this section, and don't use replace
. Here are the requirements:",
- "The input is a string with spaces and title-cased words",
- "The output is a string with the spaces between words replaced by a hyphen (-
)",
- "The output should be all lower-cased letters",
- "The output should not have any spaces"
- ],
- "challengeSeed": [
- "// the global variable",
- "var globalTitle = \"Winter Is Coming\";",
- "",
- "// Add your code below this line",
- "function urlSlug(title) {",
- " ",
- " ",
- "}",
- "// Add your code above this line",
- "",
- "var winterComing = urlSlug(globalTitle); // Should be \"winter-is-coming\""
- ],
- "tests": [
- "assert(globalTitle === \"Winter Is Coming\", 'message: The globalTitle
variable should not change.');",
- "assert(!code.match(/\\.replace/g), 'message: Your code should not use the replace
method for this challenge.');",
- "assert(urlSlug(\"Winter Is Coming\") === \"winter-is-coming\", 'message: urlSlug(\"Winter Is Coming\")
should return \"winter-is-coming\"
.');",
- "assert(urlSlug(\" Winter Is Coming\") === \"winter-is-coming\", 'message: urlSlug(\" Winter Is Coming\")
should return \"winter-is-coming\"
.');",
- "assert(urlSlug(\"A Mind Needs Books Like A Sword Needs A Whetstone\") === \"a-mind-needs-books-like-a-sword-needs-a-whetstone\", 'message: urlSlug(\"A Mind Needs Books Like A Sword Needs A Whetstone\")
should return \"a-mind-needs-books-like-a-sword-needs-a-whetstone\"
.');",
- "assert(urlSlug(\"Hold The Door\") === \"hold-the-door\", 'message: urlSlug(\"Hold The Door\")
should return \"hold-the-door\"
.');"
- ],
- "solutions": [],
- "hints": [
- "When several spaces in a row are split by space, it puts an empty string in the array.",
- "You can use the .toLowerCase() method to make the title all lower case."
- ],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dab367417b2b2512b6e",
- "title": "Use the every Method to Check that Every Element in an Array Meets a Criteria",
- "description": [
- "The every
method works with arrays to check if every element passes a particular test. It returns a Boolean value - true
if all values meet the criteria, false
if not.",
- "For example, the following code would check if every element in the numbers
array is less than 10:",
- "var numbers = [1, 5, 8, 0, 10, 11];
",
- "
numbers.every(function(currentValue) {
return currentValue < 10;
});
// Returns false
",
- "Use the every
method inside the checkPositive
function to check if every element in arr
is positive. The function should return a Boolean value."
- ],
- "challengeSeed": [
- "function checkPositive(arr) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "checkPositive([1, 2, 3, -4, 5]);"
- ],
- "tests": [
- "assert(code.match(/\\.every/g), 'message: Your code should use the every
method.');",
- "assert(!checkPositive([1, 2, 3, -4, 5]), 'message: checkPositive([1, 2, 3, -4, 5])
should return false
.');",
- "assert(checkPositive([1, 2, 3, 4, 5]), 'message: checkPositive([1, 2, 3, 4, 5])
should return true
.');",
- "assert(!checkPositive([1, -2, 3, -4, 5]), 'message: checkPositive([1, -2, 3, -4, 5])
should return false
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dab367417b2b2512b6f",
- "title": "Use the some Method to Check that Any Elements in an Array Meet a Criteria",
- "description": [
- "The some
method works with arrays to check if any element passes a particular test. It returns a Boolean value - true
if any of the values meet the criteria, false
if not.",
- "For example, the following code would check if any element in the numbers
array is less than 10:",
- "var numbers = [10, 50, 8, 220, 110, 11];
",
- "
numbers.some(function(currentValue) {
return currentValue < 10;
});
// Returns true
",
- "Use the some
method inside the checkPositive
function to check if any element in arr
is positive. The function should return a Boolean value."
- ],
- "challengeSeed": [
- "function checkPositive(arr) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "checkPositive([1, 2, 3, -4, 5]);"
- ],
- "tests": [
- "assert(code.match(/\\.some/g), 'message: Your code should use the some
method.');",
- "assert(checkPositive([1, 2, 3, -4, 5]), 'message: checkPositive([1, 2, 3, -4, 5])
should return true
.');",
- "assert(checkPositive([1, 2, 3, 4, 5]), 'message: checkPositive([1, 2, 3, 4, 5])
should return true
.');",
- "assert(!checkPositive([-1, -2, -3, -4, -5]), 'message: checkPositive([-1, -2, -3, -4, -5])
should return false
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dab367417b2b2512b70",
- "title": "Introduction to Currying and Partial Application",
- "description": [
- "The arity
of a function is the number of arguments it requires. Currying
a function means to convert a function of N arity
into N functions of arity
1.",
- "In other words, it restructures a function so it takes one argument, then returns another function that takes the next argument, and so on.",
- "Here's an example:",
- "//Un-curried function
",
- "This is useful in your program if you can't supply all the arguments to a function at one time. You can save each function call into a variable, which will hold the returned function reference that takes the next argument when it's available. Here's an example using the
function unCurried(x, y, z) {
return x + y + z;
}
//Curried function
function curried(x) {
return function(y) {
return x + y;
}
}
curried(1)(2) // Returns 3curried
function in the example above:",
- "// Call a curried function in parts:
",
- "Similarly,
var funcForY = curried(1);
var funcForZ = funcForY(2);
console.log(funcForZ(3)); // Prints 6partial application
can be described as applying a few arguments to a function at a time and returning another function that is applied to more arguments.",
- "Here's an example:",
- "//Impartial function
",
- "
function impartial(x, y, z) {
return x + y + z;
}
var partialFn = impartial.bind(this, 1, 2);
partialFn(10); // Returns 13
",
- "Fill in the body of the add
function so it uses currying to add parameters x
, y
, and z
."
- ],
- "challengeSeed": [
- "function add(x) {",
- " // Add your code below this line",
- " ",
- " ",
- " // Add your code above this line",
- "}",
- "add(10)(20)(30);"
- ],
- "tests": [
- "assert(add(10)(20)(30) === 60, 'message: add(10)(20)(30)
should return 60
.');",
- "assert(add(1)(2)(3) === 6, 'message: add(1)(2)(3)
should return 6
.');",
- "assert(add(11)(22)(33) === 66, 'message: add(11)(22)(33)
should return 66
.');",
- "assert(code.match(/[xyz]\\s*?\\+\\s*?[xyz]\\s*?\\+\\s*?[xyz]/g), 'message: Your code should include a final statement that returns x + y + z
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json
deleted file mode 100644
index 275f69bdcd..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json
+++ /dev/null
@@ -1,1212 +0,0 @@
-{
- "name": "Intermediate Algorithm Scripting",
- "order": 9,
- "time": "50 hours",
- "helpRoom": "HelpJavaScript",
- "challenges": [
- {
- "id": "a3566b1109230028080c9345",
- "title": "Sum All Numbers in a Range",
- "description": [
- "We'll pass you an array of two numbers. Return the sum of those two numbers plus the sum of all the numbers between them.",
- "The lowest number will not always come first.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function sumAll(arr) {",
- " return 1;",
- "}",
- "",
- "sumAll([1, 4]);"
- ],
- "hints": [
- "Use Math.max() to find the maximum value of two numbers.",
- "Use Math.min() to find the minimum value of two numbers.",
- "Remember to that you must add all the numbers in between so this would require a way to get those numbers."
- ],
- "solutions": [
- "function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}"
- ],
- "tests": [
- "assert(typeof sumAll([1, 4]) === 'number', 'message: sumAll([1, 4])
should return a number.');",
- "assert.deepEqual(sumAll([1, 4]), 10, 'message: sumAll([1, 4])
should return 10.');",
- "assert.deepEqual(sumAll([4, 1]), 10, 'message: sumAll([4, 1])
should return 10.');",
- "assert.deepEqual(sumAll([5, 10]), 45, 'message: sumAll([5, 10])
should return 45.');",
- "assert.deepEqual(sumAll([10, 5]), 45, 'message: sumAll([10, 5])
should return 45.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Math.max()",
- "Math.min()",
- "Array.prototype.reduce()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Suma todos los números en un rango",
- "description": [
- "Te pasaremos un vector que contiene dos números. Crea una función que devuelva la suma de esos dos números y todos los números entre ellos.",
- "El número menor no siempre será el primer elemento en el vector.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Additionner tous les nombres d'une série",
- "description": [
- "Nous te passons un tableau de deux nombres. Crée une fonction qui renvoie la somme de ces 2 nombres ainsi que tous les nombres entre ceux-ci.",
- "Le plus petit nombre ne viendra pas forcément en premier.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a5de63ebea8dbee56860f4f2",
- "title": "Diff Two Arrays",
- "description": [
- "Compare two arrays and return a new array with any items only found in one of the two given arrays, but not both. In other words, return the symmetric difference of the two arrays.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.",
- "Note
You can return the array with its elements in any order."
- ],
- "challengeSeed": [
- "function diffArray(arr1, arr2) {",
- " var newArr = [];",
- " // Same, same; but different.",
- " return newArr;",
- "}",
- "",
- "diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);"
- ],
- "solutions": [
- "function diffArray(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}"
- ],
- "tests": [
- "assert(typeof diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'message: diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
should return an array.');",
- "assert.sameMembers(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"pink wool\"]
.');",
- "assert(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 1, 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with one item.');",
- "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"diorite\", \"pink wool\"]
.');",
- "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 2, 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with two items.');",
- "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return []
.');",
- "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 0, 'message: [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an empty array.');",
- "assert.sameMembers(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5]
should return [4]
.');",
- "assert(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]).length === 1, 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5]
should return an array with one item.');",
- "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return [\"piglet\", 4]
.');",
- "assert(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]).length === 2, 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return an array with two items.');",
- "assert.sameMembers(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
.');",
- "assert(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]).length === 3, 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return an array with three items.');",
- "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
.');",
- "assert(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]).length === 6, 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return an array with six items.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Comparison Operators",
- "Array.prototype.slice()",
- "Array.prototype.filter()",
- "Array.prototype.indexOf()",
- "Array.prototype.concat()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Obtén la diferencia entre dos vectores",
- "description": [
- "Crea una función que compare dos vectores y que devuelva un nuevo vector que contenga los elementos que sólo se encuentre en uno de los vectores dados, pero no en ambos En otras palabras, devuelve la diferencia simétrica entre los dos vectores.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Comparer 2 arrays",
- "description": [
- "Compare les 2 tableaux donnés et renvoie un nouvel tableau avec les éléments trouvé dans un seul des deux tableaux, pas dans les deux. En d'autres termes, renvoie la différence symétrique des deux tableaux.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a39963a4c10bc8b4d4f06d7e",
- "title": "Seek and Destroy",
- "description": [
- "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.",
- "Note
You have to use the arguments
object.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function destroyer(arr) {",
- " // Remove all the values",
- " return arr;",
- "}",
- "",
- "destroyer([1, 2, 3, 1, 2, 3], 2, 3);"
- ],
- "tests": [
- "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: destroyer([1, 2, 3, 1, 2, 3], 2, 3)
should return [1, 1]
.');",
- "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'message: destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3)
should return [1, 5, 1]
.');",
- "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'message: destroyer([3, 5, 1, 2, 2], 2, 3, 5)
should return [1]
.');",
- "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'message: destroyer([2, 3, 2, 3], 2, 3)
should return []
.');",
- "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'message: destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53)
should return [\"hamburger\"]
.');",
- "assert.deepEqual(destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\"), [12,92,65], 'message: destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\")
should return [12,92,65]
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function destroyer(arr) {\n var hash = Object.create(null);\n [].slice.call(arguments, 1).forEach(function(e) {\n hash[e] = true;\n });\n // Remove all the values\n return arr.filter(function(e) { return !(e in hash);});\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);\n"
- ],
- "MDNlinks": [
- "Arguments object",
- "Array.prototype.filter()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Buscar y Destruir",
- "description": [
- "Se te proveerá un arreglo inicial (el primer argumento en la función destroyer
), seguido por uno o más argumentos. Elimina todos los elementos del arreglo inicial que tengan el mismo valor que el resto de argumentos.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Buscar e Destruir",
- "description": [
- "Será fornecido a você uma matriz inicial (o primeiro argumento da função destroyer), seguido por um ou mais argumentos. Remova todos os elementos da matriz inicial que possuem o mesmo valor desses argumentos.",
- "Nota
Você precisa usar o objeto arguments
.",
- "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a8e512fbe388ac2f9198f0fa",
- "title": "Wherefore art thou",
- "description": [
- "Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching name and value pairs (second argument). Each name and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.",
- "For example, if the first argument is [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]
, and the second argument is { last: \"Capulet\" }
, then you must return the third object from the array (the first argument), because it contains the name and its value, that was passed on as the second argument.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function whatIsInAName(collection, source) {",
- " // What's in a name?",
- " var arr = [];",
- " // Only change code below this line",
- " ",
- " ",
- " // Only change code above this line",
- " return arr;",
- "}",
- "",
- "whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });"
- ],
- "solutions": [
- "function whatIsInAName(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}"
- ],
- "tests": [
- "assert.deepEqual(whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
should return [{ first: \"Tybalt\", last: \"Capulet\" }]
.');",
- "assert.deepEqual(whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 }), [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], 'message: whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 })
should return [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }]
.');",
- "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.');",
- "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 }), [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 })
should return [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.');",
- "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, {\"bat\":2}], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }]
.');",
- "assert.deepEqual(whatIsInAName([{ \"a\": 1, \"b\": 2, \"c\": 3 }], { \"a\": 1, \"b\": 9999, \"c\": 3 }), [], 'message: whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3})
should return []
');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Global Object",
- "Object.prototype.hasOwnProperty()",
- "Object.keys()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "¿Dónde estás que no te veo?",
- "description": [
- "Crea una función que busque en un vector de objetos (primer argumento) y devuelva un vector con todos los objetos que compartan el valor indicado para una propiedad dada (segundo argumento). Cada pareja de propiedad y valor debe estar presente en el objeto de la colección para ser incluido en el vector devuelto por la función",
- "Por ejemplo, si el primer argumento es [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]
, y el segundo argumento es { last: \"Capulet\" }
, entonces tu función debe devolver el tercer objeto del vector en el primer argumento, ya que contiene la propiedad y el valor indicados en el segundo argumento.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "O Roméo! Roméo!",
- "description": [
- "Écris une fonction qui parcourt un array d'objets (premier argument) et renvoie un array de tous les objects ayant les paires de nom/valeur correspondantes à l'objet donné (second argument). Chaque paire de nom et de valeur de l'objet source doit être présente dans les objects renvoyés.",
- "Par exemple, si le premier argument est [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]
, et le second argument est { last: \"Capulet\" }
, tu dois renvoyer le troisième objet de l'array (premier argument), parce qu'il contient le nom et sa valeur, donnés en deuxième argument.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a103376db3ba46b2d50db289",
- "title": "Spinal Tap Case",
- "description": [
- "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function spinalCase(str) {",
- " // \"It's such a fine line between stupid, and clever.\"",
- " // --David St. Hubbins",
- " return str;",
- "}",
- "",
- "spinalCase('This Is Spinal Tap');"
- ],
- "solutions": [
- "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}"
- ],
- "tests": [
- "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'message: spinalCase(\"This Is Spinal Tap\")
should return \"this-is-spinal-tap\"
.');",
- "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'message: spinalCase(\"thisIsSpinal
should return \"this-is-spinal-tap\"
.');",
- "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'message: spinalCase(\"The_Andy_
should return \"the-andy-griffith-show\"
.');",
- "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'message: spinalCase(\"Teletubbies say Eh-oh\")
should return \"teletubbies-say-eh-oh\"
.');",
- "assert.strictEqual(spinalCase(\"AllThe-small Things\"), \"all-the-small-things\", 'message: spinalCase(\"AllThe-small Things\")
should return \"all-the-small-things\"
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "RegExp",
- "String.prototype.replace()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "separado-por-guiones",
- "description": [
- "Convierte la cadena de texto que se te pasa al formato spinal case. Spinal case es cuando escribes todas las palabras en-minúsculas-unidas-por-guiones.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Trait d'union",
- "description": [
- "Convertis la chaîne de caractères en spinal case. Spinal case correspond au bas-de-casse-séparé-par-des-tirets.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "aa7697ea2477d1316795783b",
- "title": "Pig Latin",
- "description": [
- "Translate the provided string to pig latin.",
- "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".",
- "If a word begins with a vowel you just add \"way\" to the end.",
- "Input strings are guaranteed to be English words in all lowercase.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function translatePigLatin(str) {",
- " return str;",
- "}",
- "",
- "translatePigLatin(\"consonant\");"
- ],
- "solutions": [
- "function translatePigLatin(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}"
- ],
- "tests": [
- "assert.deepEqual(translatePigLatin(\"california\"), \"aliforniacay\", 'message: translatePigLatin(\"california\")
should return \"aliforniacay\".');",
- "assert.deepEqual(translatePigLatin(\"paragraphs\"), \"aragraphspay\", 'message: translatePigLatin(\"paragraphs\")
should return \"aragraphspay\".');",
- "assert.deepEqual(translatePigLatin(\"glove\"), \"oveglay\", 'message: translatePigLatin(\"glove\")
should return \"oveglay\".');",
- "assert.deepEqual(translatePigLatin(\"algorithm\"), \"algorithmway\", 'message: translatePigLatin(\"algorithm\")
should return \"algorithmway\".');",
- "assert.deepEqual(translatePigLatin(\"eight\"), \"eightway\", 'message: translatePigLatin(\"eight\")
should return \"eightway\".');",
- "assert.deepEqual(translatePigLatin(\"schwartz\"), \"artzschway\", 'message: Should handle words where the first vowel comes in the end of the word.');",
- "assert.deepEqual(translatePigLatin(\"rhythm\"), \"rhythmay\", 'message: Should handle words without vowels.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Array.prototype.indexOf()",
- "Array.prototype.push()",
- "Array.prototype.join()",
- "String.prototype.substring()",
- "String.prototype.split()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Latín de los cerdos",
- "description": [
- "Traduce la cadena de texto que se te provee al Latín de los cerdos (Pig Latin)",
- "Pig Latin toma la primera consonante (o grupo de consonantes) de una palabra en inglés, la mueve al final de la palabra y agrega un \"ay\".",
- "Si la palabra comienza con una vocal, simplemente añade \"way\" al final.",
- "Cadenas de entrada están garantizadas de ser palabras en Inglés en minúscula.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Pig latin",
- "description": [
- "Traduis la phrase donnée en pig latin (verlan anglais)",
- "Le Pig Latin prend la ou les première(s) consonne(s) d'un mot en anglais et les mets à la fin du mot accompagné par le suffixe \"ay\".",
- "Si un mot commence par une voyelle ajoute \"way\" à la fin du mot.",
- "Les chaînes de caractères entrées sont garanties d'être des mots anglais, en lettres minuscules.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a0b5010f579e69b815e7c5d6",
- "title": "Search and Replace",
- "description": [
- "Perform a search and replace on the sentence using the arguments provided and return the new sentence.",
- "First argument is the sentence to perform the search and replace on.",
- "Second argument is the word that you will be replacing (before).",
- "Third argument is what you will be replacing the second argument with (after).",
- "Note
Preserve the case of the first character in the original word when you are replacing it. For example if you mean to replace the word \"Book\" with the word \"dog\", it should be replaced as \"Dog\"",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function myReplace(str, before, after) {",
- " return str;",
- "}",
- "",
- "myReplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");"
- ],
- "solutions": [
- "function myReplace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}"
- ],
- "tests": [
- "assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: myReplace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\".');",
- "assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\".');",
- "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
should return \"This has a spelling error\".');",
- "assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: myReplace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\".');",
- "assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\"), \"Let us get back to more Algorithms\", 'message: myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\")
should return \"Let us get back to more Algorithms\".');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Array.prototype.splice()",
- "String.prototype.replace()",
- "Array.prototype.join()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Buscar y reemplazar",
- "description": [
- "Crea una función que busque un fragmento en una frase dada y lo reemplace por otro fragmento, devolviendo la nueva frase.",
- "El primer argumento es la frase en la que se ejecutará la búsqueda y el reemplazo",
- "El segundo argumento es la palabra que se va a reemplazar",
- "El tercer argumento es lo que reemplazará a la palabra indicada en el segundo argumento",
- "NOTA: Debes respetar mayúsculas y minúsculas de la palabra original cuando ejecutes el reemplazo. Por ejemplo, si quisieras reemplazar la palabra \"Libro\" con la palabra \"perro\", deberías insertar en vez la palabra \"Perro\"",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Cherche et remplace",
- "description": [
- "Crée une fonction qui cherche et remplace une partie de la phrase en utilisant les arguments et renvoie la nouvelle phrase.",
- "Le premier argument est la phrase à modifier.",
- "Le deuxième argument est le mot à remplacer (avant).",
- "Le troisième argument est le mot qui doit remplacer le deuxième argument (après).",
- "NB: Tu dois respecter les majuscules ou miniscules du mot originel que tu remplaces. Par exemple, si tu veux remplacer le mot \"Livre\" par \"chien\", tu devras le remplacer par \"Chien\"",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "afd15382cdfb22c9efe8b7de",
- "title": "DNA Pairing",
- "description": [
- "The DNA strand is missing the pairing element. Take each character, get its pair, and return the results as a 2d array.",
- "Base pairs are a pair of AT and CG. Match the missing element to the provided character.",
- "Return the provided character as the first element in each array.",
- "For example, for the input GCG, return [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
- "The character and its pair are paired up in an array, and all the arrays are grouped into one encapsulating array.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function pairElement(str) {",
- " return str;",
- "}",
- "",
- "pairElement(\"GCG\");"
- ],
- "solutions": [
- "var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pairElement(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}"
- ],
- "tests": [
- "assert.deepEqual(pairElement(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'message: pairElement(\"ATCGA\")
should return [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]
.');",
- "assert.deepEqual(pairElement(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: pairElement(\"TTGAG\")
should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]
.');",
- "assert.deepEqual(pairElement(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: pairElement(\"CTCTA\")
should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Array.prototype.push()",
- "String.prototype.split()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Emparejando bases de ADN",
- "description": [
- "A la cadena de ADN que se te pasa le hace falta una hebra. Toma cada una de las letras, obtén su pareja correspondiente y devuelve los resultados en un segundo vector",
- "Parejas de bases son pares de AT y CG. Encuentra el elemento que hace falta para cada una de las letras que se te presentan.",
- "Devuelve la letra que se te provee como el primer elemento en cada vector",
- "Por ejemplo, si te pasáramos la cadena GCG, tu función debería devolver el vector: [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
- "Cada letra que se te provee y su pareja deben estar contenidos en un vector, y cada uno de estos vectores debe estar contenidos en un vector.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Coupler les bases d'ADN",
- "description": [
- "Une base d'ADN a perdu sa paire. Assemble chaque paire de caractères et renvoie les résultats dans un second tableau.",
- "Les paires de bases sont des paires d'AT et CG. Associe l'élement manquant au caractère donné.",
- "Renvoie le caractère donné comme premier élément de chaque tableau.",
- "Par exemple, pour GCG, il faut renvoyer [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
- "Chaque caractère et sa paire sont couplées dans un tableau, et tous les tableaux sont groupés dans un tableau.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "af7588ade1100bde429baf20",
- "title": "Missing letters",
- "description": [
- "Find the missing letter in the passed letter range and return it.",
- "If all letters are present in the range, return undefined.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function fearNotLetter(str) {",
- " return str;",
- "}",
- "",
- "fearNotLetter(\"abce\");"
- ],
- "solutions": [
- "function fearNotLetter (str) {\n for (var i = str.charCodeAt(0); i <= str.charCodeAt(str.length - 1); i++) {\n var letter = String.fromCharCode(i);\n if (str.indexOf(letter) === -1) {\n return letter;\n }\n }\n \n return undefined;\n}"
- ],
- "tests": [
- "assert.deepEqual(fearNotLetter('abce'), 'd', 'message: fearNotLetter(\"abce\")
should return \"d\".');",
- "assert.deepEqual(fearNotLetter('abcdefghjklmno'), 'i', 'message: fearNotLetter(\"abcdefghjklmno\")
should return \"i\".');",
- "assert.deepEqual(fearNotLetter('stvwx'), 'u', 'message: fearNotLetter(\"stvwx\")
should return \"u\".');",
- "assert.deepEqual(fearNotLetter('bcdf'), 'e', 'message: fearNotLetter(\"bcdf\")
should return \"e\".');",
- "assert.isUndefined(fearNotLetter('abcdefghijklmnopqrstuvwxyz'), 'message: fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\")
should return undefined.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "String.prototype.charCodeAt()",
- "String.fromCharCode()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Letras perdidas",
- "description": [
- "Crea una función que devuelva la letra que falta en el rango de letras que se le pasa",
- "Si todas las letras en el rango están presentes, la función debe devolver undefined.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Lettres perdues",
- "description": [
- "Crée une fonction qui renvoie la lettre manquante dans la série.",
- "Si aucune lettre n'est manquante, renvoie undefined.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a105e963526e7de52b219be9",
- "title": "Sorted Union",
- "description": [
- "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.",
- "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.",
- "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.",
- "Check the assertion tests for examples.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function uniteUnique(arr) {",
- " return arr;",
- "}",
- "",
- "uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);"
- ],
- "solutions": [
- "function uniteUnique(arr) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}"
- ],
- "tests": [
- "assert.deepEqual(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])
should return [1, 3, 2, 5, 4]
.');",
- "assert.deepEqual(uniteUnique([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: uniteUnique([1, 3, 2], [1, [5]], [2, [4]])
should return [1, 3, 2, [5], [4]]
.');",
- "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: uniteUnique([1, 2, 3], [5, 2, 1])
should return [1, 2, 3, 5]
.');",
- "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'message: uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])
should return [1, 2, 3, 5, 4, 6, 7, 8]
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Arguments object",
- "Array.prototype.reduce()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Intersección ordenada",
- "description": [
- "Escribe una función que tome dos o más vectores y que devuelva un nuevo vector con los valores únicos en el orden de aparición de los vectores que se te pasaron",
- "En otra palabras, todos los valores presentes en todos los vectores deben aparecer en el vector final en su orden original, pero sin duplicados.",
- "Los valores únicos deben aparecer en el orden original, pero el vector final no necesariamente debe mostrar los elementos en orden numérico.",
- "Puedes usar de referencia las pruebas de verificación si necesitas ejemplos.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Union arrangée",
- "description": [
- "Crée une fonction qui accepte deux tableaux ou plus et renvoie un nouvel array de valeurs uniques dans l'ordre des tableaux donnés.",
- "En d'autres termes, toutes les valeurs des tableaux doivent être incluses dans l'ordre originel, sans doublon dans le tableau final.",
- "Les valeurs uniques doivent être classées dans l'ordre originel, mais le tableau final ne doit pas être classé par ordre croissant.",
- "Réfère toi aux test pour plus d'examples.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a6b0bb188d873cb2c8729495",
- "title": "Convert HTML Entities",
- "description": [
- "Convert the characters &
, <
, >
, \"
(double quote), and '
(apostrophe), in a string to their corresponding HTML entities.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function convertHTML(str) {",
- " // :)",
- " return str;",
- "}",
- "",
- "convertHTML(\"Dolce & Gabbana\");"
- ],
- "solutions": [
- "var MAP = { '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''};\n\nfunction convertHTML(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}"
- ],
- "tests": [
- "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'message: convertHTML(\"Dolce & Gabbana\")
should return Dolce & Gabbana
.');",
- "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'message: convertHTML(\"Hamburgers < Pizza < Tacos\")
should return Hamburgers < Pizza < Tacos
.');",
- "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'message: convertHTML(\"Sixty > twelve\")
should return Sixty > twelve
.');",
- "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'message: convertHTML('Stuff in \"quotation marks\"')
should return Stuff in "quotation marks"
.');",
- "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'message: convertHTML(\"Schindler's List\")
should return Schindler's List
.');",
- "assert.match(convertHTML('<>'), /<>/, 'message: convertHTML(\"<>\")
should return <>
.');",
- "assert.strictEqual(convertHTML('abc'), 'abc', 'message: convertHTML(\"abc\")
should return abc
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "RegExp",
- "HTML Entities",
- "String.prototype.replace()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Convierte entidades HTML",
- "description": [
- "Convierte los caracteres &
, <
,
>
,
\"
' (comilla), y
'
(apóstrofe), contenidos en la cadena de texto que se te pasa, en sus entidades HTML correspondientes",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Convertir les entités HTML",
- "description": [
- "Convertis les caractères
&
, <
,
>
,
\"
' (guillemet), y
'
(apostrophe), contenus dans la chaîne de caractères en entités HTML.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a5229172f011153519423690",
- "title": "Sum All Odd Fibonacci Numbers",
- "description": [
- "Given a positive integer
num
, return the sum of all odd Fibonacci numbers that are less than or equal to num
.",
- "The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.",
- "For example, sumFibs(10)
should return 10
because all odd Fibonacci numbers less than or equal to 10
are 1, 1, 3, and 5.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function sumFibs(num) {",
- " return num;",
- "}",
- "",
- "sumFibs(4);"
- ],
- "solutions": [
- "function sumFibs(num) {\n var a = 1; \n var b = 1;\n var s = 0;\n while (a <= num) {\n if (a % 2 !== 0) { \n s += a; \n }\n a = [b, b=b+a][0];\n }\n return s;\n}"
- ],
- "tests": [
- "assert(typeof sumFibs(1) === \"number\", 'message: sumFibs(1)
should return a number.');",
- "assert(sumFibs(1000) === 1785, 'message: sumFibs(1000)
should return 1785.');",
- "assert(sumFibs(4000000) === 4613732, 'message: sumFibs(4000000)
should return 4613732.');",
- "assert(sumFibs(4) === 5, 'message: sumFibs(4)
should return 5.');",
- "assert(sumFibs(75024) === 60696, 'message: sumFibs(75024)
should return 60696.');",
- "assert(sumFibs(75025) === 135721, 'message: sumFibs(75025)
should return 135721.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Remainder"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Suma todos los números de Fibonacci que son impares",
- "description": [
- "Crea una función que devuelva la suma de todos los números impares en la secuencia de Fibonacci hasta el número que se le pasa como argumento, incluyéndolo en caso de ser un número de la secuencia.",
- "Los primeros números de la secuencia son 1, 1, 2, 3, 5 y 8, y cada número siguiente es la suma de los dos números anteriores.",
- "Por ejemplo, si se te pasa el número 4, la función deberá devolver 5, ya que los números impares menores que 4 son 1, 1 y 3.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Additionner tous les nombre de Fibonacci impairs",
- "description": [
- "Crée une fonction qui additionne tous les nombre de Fibonacci jusqu'au nombre donné (inclus si c'est un nombre de Fibonacci).",
- "Les premiers chiffres de la séquence sont 1, 1, 2, 3, 5 y 8, et chaque nombre correspond à la somme des deux nombres précédents.",
- "Par example, pour le chiffre 4, la fonction doit retourner 5, puisque les chiffres précédent 4 sont 1, 1 et 3.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a3bfc1673c0526e06d3ac698",
- "title": "Sum All Primes",
- "description": [
- "Sum all the prime numbers up to and including the provided number.",
- "A prime number is defined as a number greater than one and having only two divisors, one and itself. For example, 2 is a prime number because it's only divisible by one and two.",
- "The provided number may not be a prime.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function sumPrimes(num) {",
- " return num;",
- "}",
- "",
- "sumPrimes(10);"
- ],
- "solutions": [
- "function eratosthenesArray(n) {\n var primes = [];\n if (n > 2) {\n var half = n>>1;\n var sieve = Array(half);\n for (var i = 1, limit = Math.sqrt(n)>>1; i <= limit; i++) {\n if (!sieve[i]) {\n for (var step = 2*i+1, j = (step*step)>>1; j < half; j+=step) {\n sieve[j] = true;\n }\n }\n }\n primes.push(2);\n for (var p = 1; p < half; p++) {\n if (!sieve[p]) primes.push(2*p+1);\n }\n }\n return primes;\n}\n\nfunction sumPrimes(num) {\n return eratosthenesArray(num+1).reduce(function(a,b) {return a+b;}, 0);\n}\n\nsumPrimes(10);"
- ],
- "tests": [
- "assert.deepEqual(typeof sumPrimes(10), 'number', 'message: sumPrimes(10)
should return a number.');",
- "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10)
should return 17.');",
- "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977)
should return 73156.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "For Loops",
- "Array.prototype.push()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Suma todos los números primos",
- "description": [
- "Suma todos los números primos hasta, e incluyendo, el número que se te pasa",
- "Números primos son todos aquellos que sólo son divisibles entre 1 y entre sí mismos. Por ejemplo, el número 2 es primo porque solo es divisible por 1 y por 2. Por el contrario, el número 1 no es primo, ya que sólo puede dividirse por sí mismo",
- "El número que se le provee a la función no puede ser primo",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Additionner tous les nombres primaires",
- "description": [
- "Additionne tous les nombres primaires jusqu'au nombre donné (inclus).",
- "Un nombre primaire est un nombre divisible que par 1 ou par lui-même (plus grand que 1). Par exemple, 2 est un nombre primaire puisqu'il n'est divisible que par 1 et 2. 1 n'est pas primaire puiqu'il n'est divisible que par lui-même.",
- "Le nombre donné en argument n'est pas forcément un nombre primaire.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "ae9defd7acaf69703ab432ea",
- "title": "Smallest Common Multiple",
- "description": [
- "Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by all sequential numbers in the range between these parameters.",
- "The range will be an array of two numbers that will not necessarily be in numerical order.",
- "For example, if given 1 and 3, find the smallest common multiple of both 1 and 3 that is also evenly divisible by all numbers between 1 and 3. The answer here would be 6.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function smallestCommons(arr) {",
- " return arr;",
- "}",
- "",
- "",
- "smallestCommons([1,5]);"
- ],
- "solutions": [
- "function gcd(a, b) {\n while (b !== 0) {\n a = [b, b = a % b][0];\n }\n return a;\n}\n\nfunction lcm(a, b) {\n return (a * b) / gcd(a, b);\n}\n\nfunction smallestCommons(arr) {\n arr.sort(function(a,b) {return a-b;});\n var rng = [];\n for (var i = arr[0]; i <= arr[1]; i++) {\n rng.push(i);\n }\n return rng.reduce(lcm);\n}"
- ],
- "tests": [
- "assert.deepEqual(typeof smallestCommons([1, 5]), 'number', 'message: smallestCommons([1, 5])
should return a number.');",
- "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5])
should return 60.');",
- "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1])
should return 60.');",
- "assert.deepEqual(smallestCommons([2, 10]), 2520, 'message: smallestCommons([2, 10])
should return 2520.');",
- "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13])
should return 360360.');",
- "assert.deepEqual(smallestCommons([23, 18]), 6056820, 'message: smallestCommons([23, 18])
should return 6056820.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Smallest Common Multiple"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Mínimo común múltiplo",
- "description": [
- "En el ejercicio se te provee un vector con dos números. Crea una función que encuentre el número más pequeño que sea divisible entre ambos números, así como entre todos los números enteros entre ellos.",
- "Tu función debe aceptar como argumento un vector con dos números, los cuales no necesariamente estarán en orden.",
- "Por ejemplo, si se te pasan los números 1 y 3, deberás encontrar el mínimo común múltiplo de 1 y 3 que es divisible por todos los números entre 1 y 3.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Plus petit commun multiple",
- "description": [
- "Cherche le plus petit commun multiple qui soit divisible par les deux nombres donnés et par les nombres de la série entre ces deux nombres.",
- "La série est un tableau de deux nombres qui ne seront pas nécessairement dans l'ordre croissant.",
- "Par exemple, pour 1 et 3, il faut trouver le plus petit commun multiple de 1 et 3 mais aussi des nombres entre 1 et 3/",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a5deed1811a43193f9f1c841",
- "title": "Drop it",
- "description": [
- "Given the array arr
, iterate through and remove each element starting from the first element (the 0 index) until the function func
returns true
when the iterated element is passed through it.",
- "Then return the rest of the array once the condition is satisfied, otherwise, arr
should be returned as an empty array.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function dropElements(arr, func) {",
- " // Drop them elements.",
- " return arr;",
- "}",
- "",
- "dropElements([1, 2, 3], function(n) {return n < 3; });"
- ],
- "solutions": [
- "function dropElements(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}"
- ],
- "tests": [
- "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n >= 3;}), [3, 4], 'message: dropElements([1, 2, 3, 4], function(n) {return n >= 3;})
should return [3, 4]
.');",
- "assert.deepEqual(dropElements([0, 1, 0, 1], function(n) {return n === 1;}), [1, 0, 1], 'message: dropElements([0, 1, 0, 1], function(n) {return n === 1;})
should return [1, 0, 1]
.');",
- "assert.deepEqual(dropElements([1, 2, 3], function(n) {return n > 0;}), [1, 2, 3], 'message: dropElements([1, 2, 3], function(n) {return n > 0;})
should return [1, 2, 3]
.');",
- "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: dropElements([1, 2, 3, 4], function(n) {return n > 5;})
should return []
.');",
- "assert.deepEqual(dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;}), [7, 4], 'message: dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;})
should return [7, 4]
.');",
- "assert.deepEqual(dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;}), [3, 9, 2], 'message: dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;})
should return [3, 9, 2]
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Arguments object",
- "Array.prototype.shift()",
- "Array.prototype.slice()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "¡Fuera de aquí!",
- "description": [
- "Toma los elementos contenidos en el vector que se te provee en el primer argumento de la función y elimínalos uno por uno, hasta que la función provista en el segundo argumento devuelva true.",
- "Retorna el resto del vector, de lo contrario retorna un vector vacío.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Laisse tomber",
- "description": [
- "Écarte les éléments du tableau (premier argument), en commençant par la gauche, jusqu'à ce la fonction (second argument) renvoie true.",
- "Renvoie le reste du tableau, ou dans le cas contraire un tableau vide",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "ab306dbdcc907c7ddfc30830",
- "title": "Steamroller",
- "description": [
- "Flatten a nested array. You must account for varying levels of nesting.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function steamrollArray(arr) {",
- " // I'm a steamroller, baby",
- " return arr;",
- "}",
- "",
- "steamrollArray([1, [2], [3, [[4]]]]);"
- ],
- "solutions": [
- "function steamrollArray(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamrollArray(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}"
- ],
- "tests": [
- "assert.deepEqual(steamrollArray([[[\"a\"]], [[\"b\"]]]), [\"a\", \"b\"], 'message: steamrollArray([[[\"a\"]], [[\"b\"]]])
should return [\"a\", \"b\"]
.');",
- "assert.deepEqual(steamrollArray([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: steamrollArray([1, [2], [3, [[4]]]])
should return [1, 2, 3, 4]
.');",
- "assert.deepEqual(steamrollArray([1, [], [3, [[4]]]]), [1, 3, 4], 'message: steamrollArray([1, [], [3, [[4]]]])
should return [1, 3, 4]
.');",
- "assert.deepEqual(steamrollArray([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: steamrollArray([1, {}, [3, [[4]]]])
should return [1, {}, 3, 4]
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Array.isArray()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Aplanadora",
- "description": [
- "Aplana el vector anidado que se te provee. Tu función debe poder aplanar vectores de cualquier forma.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Rouleau compresseur",
- "description": [
- "Aplatis le tableau donné. Ta fonction doit pour gérer différentes formes de tableaux.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a8d97bd4c764e91f9d2bda01",
- "title": "Binary Agents",
- "description": [
- "Return an English translated sentence of the passed binary string.",
- "The binary string will be space separated.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function binaryAgent(str) {",
- " return str;",
- "}",
- "",
- "binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\");"
- ],
- "solutions": [
- "function binaryAgent(str) {\n return str.split(' ').map(function(s) { return parseInt(s, 2); }).map(function(b) { return String.fromCharCode(b);}).join('');\n}"
- ],
- "tests": [
- "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'message: binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\")
should return \"Aren't bonfires fun!?\"');",
- "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\")
should return \"I love FreeCodeCamp!\"');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "String.prototype.charCodeAt()",
- "String.fromCharCode()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Mensaje secreto",
- "description": [
- "Haz que la función devuelva el mensaje en inglés escondido en el código binario de la cadena de texto que se le pasa.",
- "La cadena de texto binaria estará separada por espacios.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Agent binaire",
- "description": [
- "Traduis la chaîne binaire donnée en anglais.",
- "La chaîne binaire comporte des espaces.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a10d2431ad0c6a099a4b8b52",
- "title": "Everything Be True",
- "description": [
- "Check if the predicate (second argument) is truthy on all elements of a collection (first argument).",
- "In other words, you are given an array collection of objects. The predicate pre
will be an object property and you need to return true
if its value is truthy
. Otherwise, return false
.",
- "In JavaScript, truthy
values are values that translate to true
when evaluated in a Boolean context.",
- "Remember, you can access object properties through either dot notation or []
notation.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function truthCheck(collection, pre) {",
- " // Is everyone being true?",
- " return pre;",
- "}",
- "",
- "truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\");"
- ],
- "solutions": [
- "function truthCheck(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}"
- ],
- "tests": [
- "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")
should return true.');",
- "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")
should return false.');",
- "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\")
should return false.');",
- "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\")
should return false');",
- "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\")
should return true');",
- "assert.strictEqual(truthCheck([{\"single\": \"yes\"}], \"single\"), true, 'message: truthCheck([{\"single\": \"yes\"}], \"single\")
should return true');",
- "assert.strictEqual(truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\")
should return false');",
- "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\")
should return false');",
- "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")
should return false');"
- ],
- "isRequired": true,
- "type": "bonfire",
- "MDNlinks": [
- "Truthy",
- "Falsy"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Que todo sea verdadero",
- "description": [
- "Verifica si la función en el segundo argumento devuelve true para todos los elementos de la colección en el primer argumento.",
- "Recuerda que puedes accesar a las propiedades de un objeto, ya sea a través de la notación por punto o de la notación por corchete usando [].",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Tout doit être vrai",
- "description": [
- "Vérifie que la fonction donnée (second argument) est vraie sur tous les éléments de la collection (premier argument).",
- "Tu peux utiliser un point ou des [] pour accéder aux propritétés de l'objet.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "a97fd23d9b809dac9921074f",
- "title": "Arguments Optional",
- "description": [
- "Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum.",
- "For example, addTogether(2, 3)
should return 5
, and addTogether(2)
should return a function.",
- "Calling this returned function with a single argument will then return the sum:",
- "var sumTwoAnd = addTogether(2);
",
- "sumTwoAnd(3)
returns 5
.",
- "If either argument isn't a valid number, return undefined.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function addTogether() {",
- " return false;",
- "}",
- "",
- "addTogether(2,3);"
- ],
- "solutions": [
- "function addTogether() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}"
- ],
- "tests": [
- "assert.deepEqual(addTogether(2, 3), 5, 'message: addTogether(2, 3)
should return 5.');",
- "assert.deepEqual(addTogether(2)(3), 5, 'message: addTogether(2)(3)
should return 5.');",
- "assert.isUndefined(addTogether(\"http://bit.ly/IqT6zt\"), 'message: addTogether(\"http://bit.ly/IqT6zt\")
should return undefined.');",
- "assert.isUndefined(addTogether(2, \"3\"), 'message: addTogether(2, \"3\")
should return undefined.');",
- "assert.isUndefined(addTogether(2)([3]), 'message: addTogether(2)([3])
should return undefined.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Closures",
- "Arguments object"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Argumentos opcionales",
- "description": [
- "Crea una función que sume dos argumentos. Si sólo se le pasa un argumento a la función, haz que devuelva otra función que acepte un argumento y que devuelva la suma correspondiente.",
- "Por ejemplo, add(2, 3)
debe devolver 5
, y add(2)
debe devolver una función.",
- "Al llamar esta función con un único argumento devolverá la suma:",
- "var sumTwoAnd = add(2);
",
- "sumTwoAnd(3)
devuelve 5
.",
- "Si alguno de los argumentos no es un número válido, haz que devuelva undefined.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Arguments optionnels",
- "description": [
- "Crée une fonction qui additionne deux arguments. Si un seul argument est donné, renvoie une fonction qui attend un argument et renvoie la somme.",
- "Par exemple, add(2, 3)
, doit renvoyer 5
, et add(2)
doit renvoyer une fonction.",
- "Appeler cette fonction avec un seul argument renvoie la somme:",
- "var sumTwoAnd = add(2);
",
- "sumTwoAnd(3)
renvoie 5
.",
- "Si aucun argument n'est un nombre, renvoie undefined.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- },
- "guideUrl":"https://guide.freecodecamp.org/certificates/arguments-optional"
- },
- {
- "id": "a2f1d72d9b908d0bd72bb9f6",
- "title": "Make a Person",
- "description": [
- "Fill in the object constructor with the following methods below:",
- "getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
",
- "Run the tests to see the expected output for each method.",
- "The methods that take an argument must accept only one argument and it has to be a string.",
- "These methods must be the only available means of interacting with the object.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "var Person = function(firstAndLast) {",
- " // Complete the method below and implement the others similarly",
- " this.getFullName = function() {",
- " return \"\";",
- " };",
- " return firstAndLast;",
- "};",
- "",
- "var bob = new Person('Bob Ross');",
- "bob.getFullName();"
- ],
- "solutions": [
- "var Person = function(firstAndLast) {\n\n var firstName, lastName;\n\n function updateName(str) { \n firstName = str.split(\" \")[0];\n lastName = str.split(\" \")[1]; \n }\n\n updateName(firstAndLast);\n\n this.getFirstName = function(){\n return firstName;\n };\n \n this.getLastName = function(){\n return lastName;\n };\n \n this.getFullName = function(){\n return firstName + \" \" + lastName;\n };\n \n this.setFirstName = function(str){\n firstName = str;\n };\n \n\n this.setLastName = function(str){\n lastName = str;\n };\n \n this.setFullName = function(str){\n updateName(str);\n };\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();"
- ],
- "tests": [
- "assert.deepEqual(Object.keys(bob).length, 6, 'message: Object.keys(bob).length
should return 6.');",
- "assert.deepEqual(bob instanceof Person, true, 'message: bob instanceof Person
should return true.');",
- "assert.deepEqual(bob.firstName, undefined, 'message: bob.firstName
should return undefined.');",
- "assert.deepEqual(bob.lastName, undefined, 'message: bob.lastName
should return undefined.');",
- "assert.deepEqual(bob.getFirstName(), 'Bob', 'message: bob.getFirstName()
should return \"Bob\".');",
- "assert.deepEqual(bob.getLastName(), 'Ross', 'message: bob.getLastName()
should return \"Ross\".');",
- "assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: bob.getFullName()
should return \"Bob Ross\".');",
- "assert.strictEqual((function () { bob.setFirstName(\"Haskell\"); return bob.getFullName(); })(), 'Haskell Ross', 'message: bob.getFullName()
should return \"Haskell Ross\" after bob.setFirstName(\"Haskell\")
.');",
- "assert.strictEqual((function () { var _bob=new Person('Haskell Ross'); _bob.setLastName(\"Curry\"); return _bob.getFullName(); })(), 'Haskell Curry', 'message: bob.getFullName()
should return \"Haskell Curry\" after bob.setLastName(\"Curry\")
.');",
- "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFullName(); })(), 'Haskell Curry', 'message: bob.getFullName()
should return \"Haskell Curry\" after bob.setFullName(\"Haskell Curry\")
.');",
- "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFirstName(); })(), 'Haskell', 'message: bob.getFirstName()
should return \"Haskell\" after bob.setFullName(\"Haskell Curry\")
.');",
- "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getLastName(); })(), 'Curry', 'message: bob.getLastName()
should return \"Curry\" after bob.setFullName(\"Haskell Curry\")
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Closures",
- "Details of the Object Model"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Crea una Persona",
- "description": [
- "Completa el constructor de objetos con los métodos especificados a continuación:",
- "getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
",
- "Ejecuta las pruebas para ver el resultado esperado de cada método.",
- "Las funciones que aceptan argumentos deben aceptar sólo uno, y este tiene que ser una cadena.",
- "Estos métodos deben ser el único medio para interactuar con el objeto.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "it": {
- "title": "Crea una Persona",
- "description": [
- "Completa il costruttore dell'oggetto con i metodi specificati qui sotto:",
- "getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
",
- "Esegui i test per vedere il risultato atteso per ogni metodo.",
- "I metodi che richiedono un argomento devono accettarne solo uno e questo deve essere una stringa.",
- "Questi metodi devono essere l'unica maniera possibile di interagire con l'oggetto.",
- "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te."
- ]
- },
- "pt-br": {
- "title": "Faça uma Pessoa",
- "description": [
- "Preencha o contrutor do objeto com seguintes métodos:",
- "getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
",
- "Rode os testes para ver o resultado esperado de cada método.",
- "Os métodos que recebem um argumento deve aceitar somente um argumento e deve ser uma string.",
- "Esses métodos devem ser o único meio de interação com o objeto.",
- "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "af4afb223120f7348cdfc9fd",
- "title": "Map the Debris",
- "description": [
- "Return a new array that transforms the elements' average altitude into their orbital periods (in seconds).",
- "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}
.",
- "You can read about orbital periods on Wikipedia.",
- "The values should be rounded to the nearest whole number. The body being orbited is Earth.",
- "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418 km3s-2.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function orbitalPeriod(arr) {",
- " var GM = 398600.4418;",
- " var earthRadius = 6367.4447;",
- " return arr;",
- "}",
- "",
- "orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]);"
- ],
- "solutions": [
- "function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n var TAU = 2 * Math.PI; \n return arr.map(function(obj) {\n return {\n name: obj.name,\n orbitalPeriod: Math.round(TAU * Math.sqrt(Math.pow(obj.avgAlt+earthRadius, 3)/GM))\n };\n });\n}\n\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);\n"
- ],
- "tests": [
- "assert.deepEqual(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]), [{name: \"sputnik\", orbitalPeriod: 86400}], 'message: orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}])
should return [{name: \"sputnik\", orbitalPeriod: 86400}]
.');",
- "assert.deepEqual(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}]), [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}], 'message: orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])
should return [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]
.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Math.pow()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Ubica los Escombros",
- "description": [
- "Crea una función que devuelva un nuevo arreglo que transforme la altitud promedio del elemento en su período orbital.",
- "El arreglo debe contener objetos en el formato {name: 'name', avgAlt: avgAlt}
.",
- "Puedes leer acerca de períodos orbitales en Wikipedia.",
- "Los valores deben estar redondeados al número entero más próximo. El cuerpo orbitado es la Tierra",
- "El radio de la Tierra es 6367.4447 kilómetros, y el valor GM del planeta es de 398600.4418 km3s-2.",
- "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "it": {
- "title": "Mappa i Detriti",
- "description": [
- "Ritorna un nuovo array che trasformi l'altitudine media degli elementi nel loro periodo orbitale.",
- "L'array conterrà oggetti in formato {name: 'name', avgAlt: avgAlt}
.",
- "Puoi leggere riguardo i periodi orbitali su Wikipedia.",
- "I valori devono essere arrotondati al numero intero più vicino. Il corpo attorno a cui orbitano gli elementi è la Terra.",
- "Il raggio della Terra è di 6367.4447 kilometri, e il valore GM della Terra è di 398600.4418 km3s-2.",
- "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te."
- ]
- },
- "pt-br": {
- "title": "Mapeie o Lixo espacial",
- "description": [
- "Retorne uma nova matriz que transforma a altitude média do elemento em seu período orbital.",
- "A matriz vai conter objetos no formato {name: 'name', avgAlt: avgAlt}
.",
- "Você pode ler sobre período orbital na Wikipedia.",
- "Os valores devem ser arredondados para número inteiro mais próximo. O corpe sendo orbitado é a Terra.",
- "O raio da terra é 6367.4447 quilômetros, e o valor GM da terra é 398600.4418 km3s-2.",
- "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código."
- ]
- }
- }
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json
deleted file mode 100644
index efa1583697..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json
+++ /dev/null
@@ -1,389 +0,0 @@
-{
- "name": "JavaScript Algorithms and Data Structures Projects",
- "order": 10,
- "time": "50 hours",
- "helpRoom": "HelpJavaScript",
- "challenges": [
- {
- "id": "aaa48de84e1ecc7c742e1124",
- "title": "Palindrome Checker",
- "description": [
- "Return true
if the given string is a palindrome. Otherwise, return false
.",
- "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.",
- "Note
You'll need to remove all non-alphanumeric characters (punctuation, spaces and symbols) and turn everything into the same case (lower or upper case) in order to check for palindromes.",
- "We'll pass strings with varying formats, such as \"racecar\"
, \"RaceCar\"
, and \"race CAR\"
among others.",
- "We'll also pass strings with special symbols, such as \"2A3*3a2\"
, \"2A3 3a2\"
, and \"2_A3*3#A2\"
.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
- ],
- "challengeSeed": [
- "function palindrome(str) {",
- " // Good luck!",
- " return true;",
- "}",
- "",
- "",
- "",
- "palindrome(\"eye\");"
- ],
- "tests": [
- "assert(typeof palindrome(\"eye\") === \"boolean\", 'message: palindrome(\"eye\")
should return a boolean.');",
- "assert(palindrome(\"eye\") === true, 'message: palindrome(\"eye\")
should return true.');",
- "assert(palindrome(\"_eye\") === true, 'message: palindrome(\"_eye\")
should return true.');",
- "assert(palindrome(\"race car\") === true, 'message: palindrome(\"race car\")
should return true.');",
- "assert(palindrome(\"not a palindrome\") === false, 'message: palindrome(\"not a palindrome\")
should return false.');",
- "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: palindrome(\"A man, a plan, a canal. Panama\")
should return true.');",
- "assert(palindrome(\"never odd or even\") === true, 'message: palindrome(\"never odd or even\")
should return true.');",
- "assert(palindrome(\"nope\") === false, 'message: palindrome(\"nope\")
should return false.');",
- "assert(palindrome(\"almostomla\") === false, 'message: palindrome(\"almostomla\")
should return false.');",
- "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: palindrome(\"My age is 0, 0 si ega ym.\")
should return true.');",
- "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: palindrome(\"1 eye for of 1 eye.\")
should return false.');",
- "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: palindrome(\"0_0 (: /-\\ :) 0-0\")
should return true.');",
- "assert(palindrome(\"five|\\_/|four\") === false, 'message: palindrome(\"five|\\_/|four\")
should return false.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "solutions": [
- "function palindrome(str) {\n var string = str.toLowerCase().split(/[^A-Za-z0-9]/gi).join('');\n var aux = string.split('');\n if (aux.join('') === aux.reverse().join('')){\n return true;\n }\n\n return false;\n}"
- ],
- "MDNlinks": [
- "String.prototype.replace()",
- "String.prototype.toLowerCase()"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Verifica si es palíndromo",
- "description": [
- "Crea una función que devuelva true
si una cadena de texto dada es un palíndromo, y que devuelva false
en caso contrario",
- "Un palíndromo es una palabra u oración que se escribe de la misma forma en ambos sentidos, sin tomar en cuenta signos de puntuación, espacios y sin distinguir entre mayúsculas y minúsculas.",
- "Tendrás que quitar los caracteres no alfanuméricos (signos de puntuación, espacioes y símbolos) y transformar las letras a minúsculas para poder verificar si el texto es palíndromo.",
- "Te proveeremos textos en varios formatos, como \"racecar\", \"RaceCar\", and \"race CAR\" entre otros.",
- "También vamos a pasar cadenas con símbolos especiales, tales como \"2A3*3a2\"
, \"2A3 3a2\"
, y \"2_A3*3#A2\"
.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Procure por Palíndromos",
- "description": [
- "Retorne true
se o texto fornecida é um palíndromo. Caso contrário, retorne false
.",
- "Um palíndromo é uma palavra ou sentença que é soletrada da mesma maneira tanto para a frente quanto para trás, ignorando pontuação, maiúsculas e minúsculas, e espaçamento.",
- "Nota
Você precisará remover todos caracteres não alfanuméricos (pontuação, espaços e símbolos) e transformar todas as letras em maiúsculas ou minúsculas para procurar por palíndromos.",
- "Nós vamos passar textos de vários formatos, tais como \"racecar\"
, \"RaceCar\"
e \"race CAR\"
entre outras.",
- "Nós também vamos passar textos com símbolos especiais, tais como \"2A3*3a2\"
, \"2A3 3a2\"
e \"2_A3*3#A2\"
.",
- "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "a7f4d8f2483413a6ce226cac",
- "title": "Roman Numeral Converter",
- "description": [
- "Convert the given number into a roman numeral.",
- "All roman numerals answers should be provided in upper-case.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function convertToRoman(num) {",
- " return num;",
- "}",
- "",
- "convertToRoman(36);"
- ],
- "solutions": [
- "function convertToRoman(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}"
- ],
- "tests": [
- "assert.deepEqual(convertToRoman(2), \"II\", 'message: convertToRoman(2)
should return \"II\".');",
- "assert.deepEqual(convertToRoman(3), \"III\", 'message: convertToRoman(3)
should return \"III\".');",
- "assert.deepEqual(convertToRoman(4), \"IV\", 'message: convertToRoman(4)
should return \"IV\".');",
- "assert.deepEqual(convertToRoman(5), \"V\", 'message: convertToRoman(5)
should return \"V\".');",
- "assert.deepEqual(convertToRoman(9), \"IX\", 'message: convertToRoman(9)
should return \"IX\".');",
- "assert.deepEqual(convertToRoman(12), \"XII\", 'message: convertToRoman(12)
should return \"XII\".');",
- "assert.deepEqual(convertToRoman(16), \"XVI\", 'message: convertToRoman(16)
should return \"XVI\".');",
- "assert.deepEqual(convertToRoman(29), \"XXIX\", 'message: convertToRoman(29)
should return \"XXIX\".');",
- "assert.deepEqual(convertToRoman(44), \"XLIV\", 'message: convertToRoman(44)
should return \"XLIV\".');",
- "assert.deepEqual(convertToRoman(45), \"XLV\", 'message: convertToRoman(45)
should return \"XLV\"');",
- "assert.deepEqual(convertToRoman(68), \"LXVIII\", 'message: convertToRoman(68)
should return \"LXVIII\"');",
- "assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'message: convertToRoman(83)
should return \"LXXXIII\"');",
- "assert.deepEqual(convertToRoman(97), \"XCVII\", 'message: convertToRoman(97)
should return \"XCVII\"');",
- "assert.deepEqual(convertToRoman(99), \"XCIX\", 'message: convertToRoman(99)
should return \"XCIX\"');",
- "assert.deepEqual(convertToRoman(400), \"CD\", 'message: convertToRoman(400)
should return \"CD\"');",
- "assert.deepEqual(convertToRoman(500), \"D\", 'message: convertToRoman(500)
should return \"D\"');",
- "assert.deepEqual(convertToRoman(501), \"DI\", 'message: convertToRoman(501)
should return \"DI\"');",
- "assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'message: convertToRoman(649)
should return \"DCXLIX\"');",
- "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'message: convertToRoman(798)
should return \"DCCXCVIII\"');",
- "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'message: convertToRoman(891)
should return \"DCCCXCI\"');",
- "assert.deepEqual(convertToRoman(1000), \"M\", 'message: convertToRoman(1000)
should return \"M\"');",
- "assert.deepEqual(convertToRoman(1004), \"MIV\", 'message: convertToRoman(1004)
should return \"MIV\"');",
- "assert.deepEqual(convertToRoman(1006), \"MVI\", 'message: convertToRoman(1006)
should return \"MVI\"');",
- "assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'message: convertToRoman(1023)
should return \"MXXIII\"');",
- "assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'message: convertToRoman(2014)
should return \"MMXIV\"');",
- "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'message: convertToRoman(3999)
should return \"MMMCMXCIX\"');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "Roman Numerals",
- "Array.prototype.splice()",
- "Array.prototype.indexOf()",
- "Array.prototype.join()"
- ],
- "isRequired": true,
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Convertior de números romanos",
- "description": [
- "Convierte el número dado en numeral romano.",
- "Todos los numerales romanos en las respuestas deben estar en mayúsculas.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "fr": {
- "title": "Convertir en chiffres romains",
- "description": [
- "Convertis le nombre donné en chiffres romains.",
- "Tous les chiffres romains doivent être en lettres capitales.",
- "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
- ]
- }
- }
- },
- {
- "id": "56533eb9ac21ba0edf2244e2",
- "title": "Caesars Cipher",
- "description": [
- "One of the simplest and most widely known ciphers is a Caesar cipher
, also known as a shift cipher
. In a shift cipher
the meanings of the letters are shifted by some set amount.",
- "A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus 'A' ↔ 'N', 'B' ↔ 'O' and so on.",
- "Write a function which takes a ROT13 encoded string as input and returns a decoded string.",
- "All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function rot13(str) { // LBH QVQ VG!",
- " ",
- " return str;",
- "}",
- "",
- "// Change the inputs below to test",
- "rot13(\"SERR PBQR PNZC\");"
- ],
- "tail": [
- ""
- ],
- "solutions": [
- "var lookup = {\n 'A': 'N','B': 'O','C': 'P','D': 'Q',\n 'E': 'R','F': 'S','G': 'T','H': 'U',\n 'I': 'V','J': 'W','K': 'X','L': 'Y',\n 'M': 'Z','N': 'A','O': 'B','P': 'C',\n 'Q': 'D','R': 'E','S': 'F','T': 'G',\n 'U': 'H','V': 'I','W': 'J','X': 'K',\n 'Y': 'L','Z': 'M' \n};\n\nfunction rot13(encodedStr) {\n var codeArr = encodedStr.split(\"\"); // String to Array\n var decodedArr = []; // Your Result goes here\n // Only change code below this line\n \n decodedArr = codeArr.map(function(letter) {\n if(lookup.hasOwnProperty(letter)) {\n letter = lookup[letter];\n }\n return letter;\n });\n\n // Only change code above this line\n return decodedArr.join(\"\"); // Array to String\n}"
- ],
- "tests": [
- "assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", 'message: rot13(\"SERR PBQR PNZC\")
should decode to FREE CODE CAMP
');",
- "assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", 'message: rot13(\"SERR CVMMN!\")
should decode to FREE PIZZA!
');",
- "assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", 'message: rot13(\"SERR YBIR?\")
should decode to FREE LOVE?
');",
- "assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", 'message: rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")
should decode to THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "String.prototype.charCodeAt()",
- "String.fromCharCode()"
- ],
- "challengeType": 5,
- "isRequired": true,
- "releasedOn": "January 1, 2016",
- "translations": {
- "es": {
- "title": "Cifrado César",
- "description": [
- "Uno de los cifrados más simples y ampliamente conocidos es el cifrado César
, también llamado cifrado por desplazamiento
. En un cifrado por desplazamiento
los significados de las letras se desplazan por una cierta cantidad.",
- "Un uso moderno común es el cifrado ROT13 , donde los valores de las letras se desplazan 13 espacios. De esta forma 'A' ↔ 'N', 'B' ↔ 'O' y así.",
- "Crea una función que tome una cadena de texto cifrada en ROT13 como argumento y que devuelva la cadena de texto decodificada.",
- "Todas las letras que se te pasen van a estar en mayúsculas. No transformes ningún caracter no-alfabético (por ejemplo: espacios, puntuación). Simplemente pásalos intactos.",
- "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "pt-br": {
- "title": "Cifra de César",
- "description": [
- "Uma das mais simples e mais conhecidas cifras é a cifra de César
, também conhecida como cifra de troca
. Em uma cifra de troca
os significados das letras são deslocados por um determinado valor.",
- "Um uso moderno comum é a cifra ROT13, aonde os valores das letras são deslocados por 13 lugares. Logo 'A' ↔ 'N', 'B' ↔ 'O' e assim por diante.",
- "Escreva uma função que recebe um texto criptografado com ROT13 como entrada e retorna o texto desencriptado.",
- "Todas as letras serão maiúsculas. Não transforme nenhum caracter não alfanuméricos (como espaços, pontuação), mas passe-os adiante.",
- "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "aff0395860f5d3034dc0bfc9",
- "title": "Telephone Number Validator",
- "description": [
- "Return true
if the passed string looks like a valid US phone number.",
- "The user may fill out the form field any way they choose as long as it has the format of a valid US number. The following are examples of valid formats for US numbers (refer to the tests below for other variants):",
- "555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
",
- "For this challenge you will be presented with a string such as 800-692-7753
or 8oo-six427676;laskdjf
. Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is 1
. Return true
if the string is a valid US phone number; otherwise return false
.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
- ],
- "challengeSeed": [
- "function telephoneCheck(str) {",
- " // Good luck!",
- " return true;",
- "}",
- "",
- "telephoneCheck(\"555-555-5555\");"
- ],
- "solutions": [
- "var re = /^([+]?1[\\s]?)?((?:[(](?:[2-9]1[02-9]|[2-9][02-8][0-9])[)][\\s]?)|(?:(?:[2-9]1[02-9]|[2-9][02-8][0-9])[\\s.-]?)){1}([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2}[\\s.-]?){1}([0-9]{4}){1}$/;\n\nfunction telephoneCheck(str) {\n return re.test(str);\n}\n\ntelephoneCheck(\"555-555-5555\");"
- ],
- "tests": [
- "assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", 'message: telephoneCheck(\"555-555-5555\")
should return a boolean.');",
- "assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: telephoneCheck(\"1 555-555-5555\")
should return true.');",
- "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: telephoneCheck(\"1 (555) 555-5555\")
should return true.');",
- "assert(telephoneCheck(\"5555555555\") === true, 'message: telephoneCheck(\"5555555555\")
should return true.');",
- "assert(telephoneCheck(\"555-555-5555\") === true, 'message: telephoneCheck(\"555-555-5555\")
should return true.');",
- "assert(telephoneCheck(\"(555)555-5555\") === true, 'message: telephoneCheck(\"(555)555-5555\")
should return true.');",
- "assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: telephoneCheck(\"1(555)555-5555\")
should return true.');",
- "assert(telephoneCheck(\"555-5555\") === false, 'message: telephoneCheck(\"555-5555\")
should return false.');",
- "assert(telephoneCheck(\"5555555\") === false, 'message: telephoneCheck(\"5555555\")
should return false.');",
- "assert(telephoneCheck(\"1 555)555-5555\") === false, 'message: telephoneCheck(\"1 555)555-5555\")
should return false.');",
- "assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: telephoneCheck(\"1 555 555 5555\")
should return true.');",
- "assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: telephoneCheck(\"1 456 789 4444\")
should return true.');",
- "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: telephoneCheck(\"123**&!!asdf#\")
should return false.');",
- "assert(telephoneCheck(\"55555555\") === false, 'message: telephoneCheck(\"55555555\")
should return false.');",
- "assert(telephoneCheck(\"(6054756961)\") === false, 'message: telephoneCheck(\"(6054756961)\")
should return false');",
- "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: telephoneCheck(\"2 (757) 622-7382\")
should return false.');",
- "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: telephoneCheck(\"0 (757) 622-7382\")
should return false.');",
- "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: telephoneCheck(\"-1 (757) 622-7382\")
should return false');",
- "assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: telephoneCheck(\"2 757 622-7382\")
should return false.');",
- "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: telephoneCheck(\"10 (757) 622-7382\")
should return false.');",
- "assert(telephoneCheck(\"27576227382\") === false, 'message: telephoneCheck(\"27576227382\")
should return false.');",
- "assert(telephoneCheck(\"(275)76227382\") === false, 'message: telephoneCheck(\"(275)76227382\")
should return false.');",
- "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: telephoneCheck(\"2(757)6227382\")
should return false.');",
- "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: telephoneCheck(\"2(757)622-7382\")
should return false.');",
- "assert(telephoneCheck(\"555)-555-5555\") === false, 'message: telephoneCheck(\"555)-555-5555\")
should return false.');",
- "assert(telephoneCheck(\"(555-555-5555\") === false, 'message: telephoneCheck(\"(555-555-5555\")
should return false.');",
- "assert(telephoneCheck(\"(555)5(55?)-5555\") === false, 'message: telephoneCheck(\"(555)5(55?)-5555\")
should return false.');"
- ],
- "type": "bonfire",
- "MDNlinks": [
- "RegExp"
- ],
- "challengeType": 5,
- "isRequired": true,
- "translations": {
- "es": {
- "title": "Valida Números Telefónicos de los EEUU",
- "description": [
- "Haz que la función devuelva true (verdadero) si el texto introducido parece un número válido en los EEUU.",
- "El usuario debe llenar el campo del formulario de la forma que desee siempre y cuando tenga el formato de un número válido en los EEUU. Los números mostrados a continuación tienen formatos válidos en los EEUU:",
- "555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
",
- "Para esta prueba se te presentará una cadena de texto como por ejemplo: 800-692-7753
o 8oo-six427676;laskdjf
. Tu trabajo consiste en validar o rechazar el número telefónico tomando como base cualquier combinación de los formatos anteriormente presentados. El código de área es requrido. Si el código de país es provisto, debes confirmar que este es 1
. La función debe devolver true si la cadena de texto es un número telefónico válido en los EEUU; de lo contrario, debe devolver false.",
- "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "it": {
- "title": "Verifica i numeri telefonici degli Stati Uniti",
- "description": [
- "Ritorna true
se la stringa passata come argomento è un numero valido negli Stati Uniti.",
- "L'utente può digitare qualunque stringa nel campo di inserimento, purchè sia un numero di telefono valido negli Stati Uniti. Qui sotto alcuni esempi di numeri di telefono validi negli Stati Uniti (fai riferimento ai test per le altre varianti):",
- "555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
",
- "In questo problema ti saranno presentate delle stringe come 800-692-7753
o 8oo-six427676;laskdjf
. Il tuo obiettivo è di validare o rigettare il numero di telefono basato su una qualunque combinazione dei formati specificati sopra. Il prefisso di zona è obbligatorio. Se il prefisso nazionale è presente, devi confermare che corrisponda a 1
. Ritorna true
se la stringa è un numero di telefono valido negli Stati Uniti; altrimenti ritorna false
.",
- "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te."
- ]
- },
- "pt-br": {
- "title": "Valida números telefônicos dos EUA",
- "description": [
- "Retorna true
se a string passada é um número telefônico válido nos EUA.",
- "O usuário pode preencher o campo de qualquer maneira com tanto que seja um número válido nos EUA. Os seguintes exemplos são formatos válidos para números de telefone nos EUA (baseie-se nos testes abaixo para outras variações):",
- "555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
",
- "Para esse desafio será dado a você uma string como 800-692-7753
ou 8oo-six427676;laskdjf
. Seu trabalho é validar ou rejeitar o número de telefone dos EUA baseado nos exmplos de formatos fornecidos acima. O código de área é obrigatório. Se o código do país for fornecido, você deve confirmar que o código do país é 1
. Retorne true
se a string é um número válido nos EUA; caso contrário retorne false
.",
- "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código."
- ]
- }
- }
- },
- {
- "id": "aa2e6f85cab2ab736c9a9b24",
- "title": "Cash Register",
- "description": [
- "Design a cash register drawer function checkCashRegister()
that accepts purchase price as the first argument (price
), payment as the second argument (cash
), and cash-in-drawer (cid
) as the third argument.",
- "cid
is a 2D array listing available currency.",
- "The checkCashRegister()
function should always return an object with a status
key and a change
key.",
- "Return {status: \"INSUFFICIENT_FUNDS\", change: []}
if cash-in-drawer is less than the change due, or if you cannot return the exact change.",
- "Return {status: \"CLOSED\", change: [...]}
with cash-in-drawer as the value for the key change
if it is equal to the change due.",
- "Otherwise, return {status: \"OPEN\", change: [...]}
, with the change due in coins and bills, sorted in highest to lowest order, as the value of the change
key.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.",
- "
"
- ],
- "challengeSeed": [
- "function checkCashRegister(price, cash, cid) {",
- " var change;",
- " // Here is your change, ma'am.",
- " return change;",
- "}",
- "",
- "// Example cash-in-drawer array:",
- "// [[\"PENNY\", 1.01],",
- "// [\"NICKEL\", 2.05],",
- "// [\"DIME\", 3.1],",
- "// [\"QUARTER\", 4.25],",
- "// [\"ONE\", 90],",
- "// [\"FIVE\", 55],",
- "// [\"TEN\", 20],",
- "// [\"TWENTY\", 60],",
- "// [\"ONE HUNDRED\", 100]]",
- "",
- "checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]);"
- ],
- "solutions": [
- "var denom = [\n\t{ name: 'ONE HUNDRED', val: 100},\n\t{ name: 'TWENTY', val: 20},\n\t{ name: 'TEN', val: 10},\n\t{ name: 'FIVE', val: 5},\n\t{ name: 'ONE', val: 1},\n\t{ name: 'QUARTER', val: 0.25},\n\t{ name: 'DIME', val: 0.1},\n\t{ name: 'NICKEL', val: 0.05},\n\t{ name: 'PENNY', val: 0.01}\n];\n\nfunction checkCashRegister(price, cash, cid) {\n var output = {status: null, change: []};\n var change = cash - price;\n var register = cid.reduce(function(acc, curr) {\n acc.total += curr[1];\n acc[curr[0]] = curr[1];\n return acc;\n }, {total: 0});\n if(register.total === change) {\n output.status = 'CLOSED';\n output.change = cid;\n return output;\n }\n if(register.total < change) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n var change_arr = denom.reduce(function(acc, curr) {\n var value = 0;\n while(register[curr.name] > 0 && change >= curr.val) {\n change -= curr.val;\n register[curr.name] -= curr.val;\n value += curr.val;\n change = Math.round(change * 100) / 100;\n }\n if(value > 0) {\n acc.push([ curr.name, value ]);\n }\n return acc;\n }, []);\n if(change_arr.length < 1 || change > 0) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n output.status = 'OPEN';\n output.change = change_arr;\n return output;\n}"
- ],
- "tests": [
- "assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', 'message: Currency Unit Amount Penny $0.01 (PENNY) Nickel $0.05 (NICKEL) Dime $0.1 (DIME) Quarter $0.25 (QUARTER) Dollar $1 (DOLLAR) Five Dollars $5 (FIVE) Ten Dollars $10 (TEN) Twenty Dollars $20 (TWENTY) One-hundred Dollars $100 (ONE HUNDRED) checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return an object.');",
- "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}
.');",
- "assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, 'message: checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}
.');",
- "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.');",
- "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.');",
- "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}
.');"
- ],
- "type": "bonfire",
- "isRequired": true,
- "MDNlinks": [
- "Global Object",
- "Floating Point Guide"
- ],
- "challengeType": 5,
- "translations": {
- "es": {
- "title": "Cambio Exacto",
- "description": [
- "Crea una función que simule una caja registradora que acepte el precio de compra como el primer argumento, la cantidad recibida como el segundo argumento, y la cantidad de dinero disponible en la registradora (cid) como tercer argumento",
- "cid es un arreglo bidimensional que lista la cantidad de dinero disponible",
- "La función debe devolver la cadena de texto \"Insufficient Funds\" si el cid es menor al cambio requerido. También debe devolver \"Closed\" si el cid es igual al cambio",
- "De no ser el caso, devuelve el cambio en monedas y billetes, ordenados de mayor a menor denominación.",
- "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
- ]
- },
- "it": {
- "title": "Cambio Esatto",
- "description": [
- "Scrivi una funzione che simuli un registro di cassa chiamata checkCashRegister()
che accetti il prezzo degli articoli come primo argomento (price
), la somma pagata (cash
), e la somma disponibile nel registratore di cassa (cid
) come terzo argomento.",
- "cid
è un array a due dimensioni che contiene la quantità di monete e banconote disponibili.",
- "Ritorna la stringa \"Insufficient Funds\"
se la quantità di denaro disponibile nel registratore di cassa non è abbastanza per restituire il resto. Ritorna la stringa \"Closed\"
se il denaro disponibile è esattamente uguale al resto.",
- "Altrimenti, ritorna il resto in monete e banconote, ordinate da quelle con valore maggiore a quelle con valore minore.",
- "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te."
- ]
- },
- "pt-br": {
- "title": "Troco Exato",
- "description": [
- "Crie uma função que simula uma caixa registradora chamada checkCashRegister()
e aceita o valor da compra como primeiro argumento (price
), pagamento como segundo argumento (cash
), e o dinheiro na caixa registradora (cid
) como terceiro argumento.",
- "cid
é uma matriz bidimensional que lista o dinheiro disponível.",
- "Retorne a string \"Insufficient Funds\"
se o dinheiro na caixa registradora é menor do que o troco ou se não é possível retornar o troco exato. Retorne a string \"Closed\"
se o dinheiro na caixa é igual ao troco.",
- "Case cotrário, retorne o troco em moedas e notas, ordenado do maior para menor.",
- "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código.",
- "
"
- ]
- }
- }
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
deleted file mode 100644
index 77e2e8c2aa..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
+++ /dev/null
@@ -1,1062 +0,0 @@
-{
- "name": "Object Oriented Programming",
- "order": 7,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7dac367417b2b2512b72",
- "title": "Introduction to the Object Oriented Programming Challenges",
- "description": [
- "",
- "",
- "At its core, software development solves a problem or achieves a result with computation. The software development process first defines a problem, then presents a solution. Object oriented programming is one of several major approaches to the software development process.Currency Unit Amount Penny $0.01 (PENNY) Nickel $0.05 (NICKEL) Dime $0.1 (DIME) Quarter $0.25 (QUARTER) Dollar $1 (DOLLAR) Five Dollars $5 (FIVE) Ten Dollars $10 (TEN) Twenty Dollars $20 (TWENTY) One-hundred Dollars $100 (ONE HUNDRED)
As its name implies, object oriented programming organizes code into object definitions. These are sometimes called classes, and they group together data with related behavior. The data is an object's attributes, and the behavior (or functions) are methods.
The object structure makes it flexible within a program. Objects can transfer information by calling and passing data to another object's methods. Also, new classes can receive, or inherit, all the features from a base or parent class. This helps to reduce repeated code.
Your choice of programming approach depends on a few factors. These include the type of problem, as well as how you want to structure your data and algorithms. This section covers object oriented programming principles in JavaScript.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7dac367417b2b2512b73",
- "title": "Create a Basic JavaScript Object",
- "description": [
- "Think about things people see everyday, like cars, shops, and birds. These are all objects
: tangible things people can observe and interact with.",
- "What are some qualities of these objects
? A car has wheels. Shops sell items. Birds have wings.",
- "These qualities, or properties
, define what makes up an object
. Note that similar objects
share the same properties
, but may have different values for those properties
. For example, all cars have wheels, but not all cars have the same number of wheels.",
- "Objects
in JavaScript are used to model real-world objects, giving them properties
and behavior just like their real-world counterparts. Here's an example using these concepts to create a duck
object
:",
- "let duck = {
",
- "This
name: \"Aflac\",
numLegs: 2
};duck
object
has two property/value pairs: a name
of \"Aflac\" and a numLegs
of 2.",
- "
",
- "Create a dog
object
with name
and numLegs
properties, and set them to a string and a number, respectively."
- ],
- "challengeSeed": [
- "let dog = {",
- " ",
- "};"
- ],
- "tests": [
- "assert(typeof(dog) === 'object', 'message: dog
should be an object
.');",
- "assert(typeof(dog.name) === 'string', 'message: dog
should have a name
property set to a string
.');",
- "assert(typeof(dog.numLegs) === 'number', 'message: dog
should have a numLegs
property set to a number
.');"
- ],
- "solutions": [
- "let dog = {\n name: '',\n numLegs: 4\n};"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dac367417b2b2512b74",
- "title": "Use Dot Notation to Access the Properties of an Object",
- "description": [
- "The last challenge created an object
with various properties
, now you'll see how to access the values of those properties
. Here's an example:",
- "let duck = {
",
- "Dot notation is used on the
name: \"Aflac\",
numLegs: 2
};
console.log(duck.name);
// This prints \"Aflac\" to the consoleobject
name, duck
, followed by the name of the property
, name
, to access the value of \"Aflac\".",
- "
",
- "Print both properties
of the dog
object below to your console."
- ],
- "challengeSeed": [
- "let dog = {",
- " name: \"Spot\",",
- " numLegs: 4",
- "};",
- "// Add your code below this line",
- "",
- ""
- ],
- "tests": [
- "assert(/console.log\\(.*dog\\.name.*\\)/g.test(code), 'message: Your should use console.log
to print the value for the name
property of the dog
object.');",
- "assert(/console.log\\(.*dog\\.numLegs.*\\)/g.test(code), 'message: Your should use console.log
to print the value for the numLegs
property of the dog
object.');"
- ],
- "solutions": [
- "let dog = {\n name: \"Spot\",\n numLegs: 4\n};\nconsole.log(dog.name);\nconsole.log(dog.numLegs);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dad367417b2b2512b75",
- "title": "Create a Method on an Object",
- "description": [
- "Objects
can have a special type of property
, called a method
.",
- "Methods
are properties
that are functions. This adds different behavior to an object
. Here is the duck
example with a method:",
- "let duck = {
",
- "The example adds the
name: \"Aflac\",
numLegs: 2,
sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
};
duck.sayName();
// Returns \"The name of this duck is Aflac.\"sayName
method
, which is a function that returns a sentence giving the name of the duck
.",
- "Notice that the method
accessed the name
property in the return statement using duck.name
. The next challenge will cover another way to do this.",
- "
",
- "Using the dog
object
, give it a method called sayLegs
. The method should return the sentence \"This dog has 4 legs.\""
- ],
- "challengeSeed": [
- "let dog = {",
- " name: \"Spot\",",
- " numLegs: 4,",
- " ",
- "};",
- "",
- "dog.sayLegs();"
- ],
- "tests": [
- "assert(typeof(dog.sayLegs) === 'function', 'message: dog.sayLegs()
should be a function.');",
- "assert(dog.sayLegs() === 'This dog has 4 legs.', 'message: dog.sayLegs()
should return the given string - note that punctuation and spacing matter.');"
- ],
- "solutions": [
- "let dog = {\n name: \"Spot\",\n numLegs: 4,\n sayLegs () {\n return 'This dog has ' + this.numLegs + ' legs.';\n }\n};\n\ndog.sayLegs();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dad367417b2b2512b76",
- "title": "Make Code More Reusable with the this Keyword",
- "description": [
- "The last challenge introduced a method
to the duck
object. It used duck.name
dot notation to access the value for the name
property within the return statement:",
- "sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
",
- "While this is a valid way to access the object's property, there is a pitfall here. If the variable name changes, any code referencing the original name would need to be updated as well. In a short object definition, it isn't a problem, but if an object has many references to its properties there is a greater chance for error.",
- "A way to avoid these issues is with the this
keyword:",
- "let duck = {
",
- "
name: \"Aflac\",
numLegs: 2,
sayName: function() {return \"The name of this duck is \" + this.name + \".\";}
};this
is a deep topic, and the above example is only one way to use it. In the current context, this
refers to the object that the method is associated with: duck
.",
- "If the object's name is changed to mallard
, it is not necessary to find all the references to duck
in the code. It makes the code reusable and easier to read.",
- "
",
- "Modify the dog.sayLegs
method to remove any references to dog
. Use the duck
example for guidance."
- ],
- "challengeSeed": [
- "",
- "let dog = {",
- " name: \"Spot\",",
- " numLegs: 4,",
- " sayLegs: function() {return \"This dog has \" + dog.numLegs + \" legs.\";}",
- "};",
- "",
- "dog.sayLegs();"
- ],
- "tests": [
- "assert(dog.sayLegs() === 'This dog has 4 legs.', 'message: dog.sayLegs()
should return the given string.');",
- "assert(code.match(/this\\.numLegs/g), 'message: Your code should use the this
keyword to access the numLegs
property of dog
.');"
- ],
- "solutions": [
- "let dog = {\n name: \"Spot\",\n numLegs: 4,\n sayLegs () {\n return 'This dog has ' + this.numLegs + ' legs.';\n }\n};\n\ndog.sayLegs();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dad367417b2b2512b77",
- "title": "Define a Constructor Function",
- "description": [
- "Constructors
are functions that create new objects. They define properties and behaviors that will belong to the new object. Think of them as a blueprint for the creation of new objects.",
- "Here is an example of a constructor
:",
- "function Bird() {
",
- "This
this.name = \"Albert\";
this.color = \"blue\";
this.numLegs = 2;
}constructor
defines a Bird
object with properties name
, color
, and numLegs
set to Albert, blue, and 2, respectively.",
- "Constructors
follow a few conventions:",
- "
",
- "Constructors
are defined with a capitalized name to distinguish them from other functions that are not constructors
.Constructors
use the keyword this
to set properties of the object they will create. Inside the constructor
, this
refers to the new object it will create.Constructors
define properties and behaviors instead of returning a value as other functions might.
",
- "Create a constructor
, Dog
, with properties name
, color
, and numLegs
that are set to a string, a string, and a number, respectively."
- ],
- "challengeSeed": [
- "",
- "",
- ""
- ],
- "tests": [
- "assert(typeof (new Dog()).name === 'string', 'message: Dog
should have a name
property set to a string.');",
- "assert(typeof (new Dog()).color === 'string', 'message: Dog
should have a color
property set to a string.');",
- "assert(typeof (new Dog()).numLegs === 'number', 'message: Dog
should have a numLegs
property set to a number.');"
- ],
- "solutions": [
- "function Dog (name, color, numLegs) {\n this.name = 'name';\n this.color = 'color';\n this.numLegs = 4;\n}"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dad367417b2b2512b78",
- "title": "Use a Constructor to Create Objects",
- "description": [
- "Here's the Bird
constructor from the previous challenge:",
- "function Bird() {
",
- "Notice that the
this.name = \"Albert\";
this.color = \"blue\";
this.numLegs = 2;
// \"this\" inside the constructor always refers to the object being created
}
let blueBird = new Bird();new
operator is used when calling a constructor. This tells JavaScript to create a new instance
of Bird
called blueBird
. Without the new
operator, this
inside the constructor would not point to the newly created object, giving unexpected results.",
- "Now blueBird
has all the properties defined inside the Bird
constructor:",
- "blueBird.name; // => Albert
",
- "Just like any other object, its properties can be accessed and modified:",
- "
blueBird.color; // => blue
blueBird.numLegs; // => 2blueBird.name = 'Elvira';
",
- "
blueBird.name; // => Elvira
",
- "Use the Dog
constructor from the last lesson to create a new instance of Dog
, assigning it to a variable hound
."
- ],
- "challengeSeed": [
- "function Dog() {",
- " this.name = \"Rupert\";",
- " this.color = \"brown\";",
- " this.numLegs = 4;",
- "}",
- "// Add your code below this line",
- "",
- ""
- ],
- "tests": [
- "assert(hound instanceof Dog, 'message: hound
should be created using the Dog
constructor.');",
- "assert(code.match(/new/g), 'message: Your code should use the new
operator to create an instance
of Dog
.');"
- ],
- "solutions": [
- "function Dog() {\n this.name = \"Rupert\";\n this.color = \"brown\";\n this.numLegs = 4;\n}\nconst hound = new Dog();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dae367417b2b2512b79",
- "title": "Extend Constructors to Receive Arguments",
- "description": [
- "The Bird
and Dog
constructors from last challenge worked well. However, notice that all Birds
that are created with the Bird
constructor are automatically named Albert, are blue in color, and have two legs. What if you want birds with different values for name and color? It's possible to change the properties of each bird manually but that would be a lot of work:",
- "let swan = new Bird();
",
- "Suppose you were writing a program to keep track of hundreds or even thousands of different birds in an aviary. It would take a lot of time to create all the birds, then change the properties to different values for every one.",
- "To more easily create different
swan.name = \"Carlos\";
swan.color = \"white\";Bird
objects, you can design your Bird constructor to accept parameters:",
- "function Bird(name, color) {
",
- "Then pass in the values as arguments to define each unique bird into the
this.name = name;
this.color = color;
this.numLegs = 2;
}Bird
constructor:",
- "let cardinal = new Bird(\"Bruce\", \"red\");
",
- "This gives a new instance of Bird
with name and color properties set to Bruce and red, respectively. The numLegs
property is still set to 2.",
- "The cardinal
has these properties:",
- "cardinal.name // => Bruce
",
- "The constructor is more flexible. It's now possible to define the properties for each
cardinal.color // => red
cardinal.numLegs // => 2Bird
at the time it is created, which is one way that JavaScript constructors are so useful. They group objects together based on shared characteristics and behavior and define a blueprint that automates their creation.",
- "
",
- "Create another Dog
constructor. This time, set it up to take the parameters name
and color
, and have the property numLegs
fixed at 4. Then create a new Dog
saved in a variable terrier
. Pass it two strings as arguments for the name
and color
properties."
- ],
- "challengeSeed": [
- "function Dog() {",
- " ",
- "}",
- "",
- ""
- ],
- "tests": [
- "assert((new Dog('Clifford')).name === 'Clifford', 'message: Dog
should receive an argument for name
.');",
- "assert((new Dog('Clifford', 'yellow')).color === 'yellow', 'message: Dog
should receive an argument for color
.');",
- "assert((new Dog('Clifford')).numLegs === 4, 'message: Dog
should have property numLegs
set to 4.');",
- "assert(terrier instanceof Dog, 'message: terrier
should be created using the Dog
constructor.');"
- ],
- "solutions": [
- "function Dog (name, color) {\n this.numLegs = 4;\n this.name = name;\n this.color = color;\n}\n\nconst terrier = new Dog();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dae367417b2b2512b7a",
- "title": "Verify an Object's Constructor with instanceof",
- "description": [
- "Anytime a constructor function creates a new object, that object is said to be an instance
of its constructor. JavaScript gives a convenient way to verify this with the instanceof
operator. instanceof
allows you to compare an object to a constructor, returning true
or false
based on whether or not that object was created with the constructor. Here's an example:",
- "let Bird = function(name, color) {
",
- "If an object is created without using a constructor,
this.name = name;
this.color = color;
this.numLegs = 2;
}
let crow = new Bird(\"Alexis\", \"black\");
crow instanceof Bird; // => trueinstanceof
will verify that it is not an instance of that constructor:",
- "let canary = {
",
- "
name: \"Mildred\",
color: \"Yellow\",
numLegs: 2
};
canary instanceof Bird; // => false
",
- "Create a new instance of the House
constructor, calling it myHouse
and passing a number of bedrooms. Then, use instanceof
to verify that it is an instance of House
."
- ],
- "challengeSeed": [
- "/* jshint expr: true */",
- "",
- "function House(numBedrooms) {",
- " this.numBedrooms = numBedrooms;",
- "}",
- "",
- "// Add your code below this line",
- "",
- "",
- ""
- ],
- "tests": [
- "assert(typeof myHouse.numBedrooms === 'number', 'message: myHouse
should have a numBedrooms
attribute set to a number.');",
- "assert(/myHouse\\s*instanceof\\s*House/.test(code), 'message: Be sure to verify that myHouse
is an instance of House
using the instanceof
operator.');"
- ],
- "solutions": [
- "function House(numBedrooms) {\n this.numBedrooms = numBedrooms;\n}\nconst myHouse = new House(4);\nconsole.log(myHouse instanceof House);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dae367417b2b2512b7b",
- "title": "Understand Own Properties",
- "description": [
- "In the following example, the Bird
constructor defines two properties: name
and numLegs
:",
- "function Bird(name) {
",
- "
this.name = name;
this.numLegs = 2;
}
let duck = new Bird(\"Donald\");
let canary = new Bird(\"Tweety\");name
and numLegs
are called own
properties, because they are defined directly on the instance object. That means that duck
and canary
each has its own separate copy of these properties.",
- "In fact every instance of Bird
will have its own copy of these properties.",
- "The following code adds all of the own
properties of duck
to the array ownProps
:",
- "let ownProps = [];
",
- "
for (let property in duck) {
if(duck.hasOwnProperty(property)) {
ownProps.push(property);
}
}
console.log(ownProps); // prints [ \"name\", \"numLegs\" ]
",
- "Add the own
properties of canary
to the array ownProps
."
- ],
- "challengeSeed": [
- "function Bird(name) {",
- " this.name = name;",
- " this.numLegs = 2;",
- "}",
- "",
- "let canary = new Bird(\"Tweety\");",
- "let ownProps = [];",
- "// Add your code below this line",
- "",
- "",
- ""
- ],
- "tests": [
- "assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1, 'message: ownProps
should include the values \"numLegs\"
and \"name\"
.');",
- "assert(!/\\Object.keys/.test(code), 'message: Solve this challenge without using the built in method Object.keys()
.');"
- ],
- "solutions": [
- "function Bird(name) {\n this.name = name;\n this.numLegs = 2;\n}\n\nlet canary = new Bird(\"Tweety\");\nfunction getOwnProps (obj) {\n const props = [];\n \n for (let prop in obj) {\n if (obj.hasOwnProperty(prop)) {\n props.push(prop);\n }\n }\n \n return props;\n}\n\nconst ownProps = getOwnProps(canary);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dae367417b2b2512b7c",
- "title": "Use Prototype Properties to Reduce Duplicate Code",
- "description": [
- "Since numLegs
will probably have the same value for all instances of Bird
, you essentially have a duplicated variable numLegs
inside each Bird
instance.",
- "This may not be an issue when there are only two instances, but imagine if there are millions of instances. That would be a lot of duplicated variables.",
- "A better way is to use Bird’s
prototype
. The prototype
is an object that is shared among ALL instances of Bird
. Here's how to add numLegs
to the Bird prototype
:",
- "Bird.prototype.numLegs = 2;
",
- "Now all instances of Bird
have the numLegs
property.",
- "console.log(duck.numLegs); // prints 2
",
- "Since all instances automatically have the properties on the
console.log(canary.numLegs); // prints 2prototype
, think of a prototype
as a \"recipe\" for creating objects.",
- "Note that the prototype
for duck
and canary
is part of the Bird
constructor as Bird.prototype
. Nearly every object in JavaScript has a prototype
property which is part of the constructor function that created it.",
- "
",
- "Add a numLegs
property to the prototype
of Dog
"
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name;",
- "}",
- "",
- "",
- "",
- "// Add your code above this line",
- "let beagle = new Dog(\"Snoopy\");"
- ],
- "tests": [
- "assert(beagle.numLegs !== undefined, 'message: beagle
should have a numLegs
property.');",
- "assert(typeof(beagle.numLegs) === 'number' , 'message: beagle.numLegs
should be a number.');",
- "assert(beagle.hasOwnProperty('numLegs') === false, 'message: numLegs
should be a prototype
property not an own
property.');"
- ],
- "solutions": [
- "function Dog (name) {\n this.name = name;\n}\nDog.prototype.numLegs = 4;\nlet beagle = new Dog(\"Snoopy\");"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daf367417b2b2512b7d",
- "title": "Iterate Over All Properties",
- "description": [
- "You have now seen two kinds of properties: own
properties and prototype
properties. Own
properties are defined directly on the object instance itself. And prototype
properties are defined on the prototype
.",
- "function Bird(name) {
",
- "Here is how you add
this.name = name; //own property
}
Bird.prototype.numLegs = 2; // prototype property
let duck = new Bird(\"Donald\");duck’s
own
properties to the array ownProps
and prototype
properties to the array prototypeProps
:",
- "let ownProps = [];
",
- "
let prototypeProps = [];
for (let property in duck) {
if(duck.hasOwnProperty(property)) {
ownProps.push(property);
} else {
prototypeProps.push(property);
}
}
console.log(ownProps); // prints [\"name\"]
console.log(prototypeProps); // prints [\"numLegs\"]
",
- "Add all of the own
properties of beagle
to the array ownProps
. Add all of the prototype
properties of Dog
to the array prototypeProps
."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name;",
- "}",
- "",
- "Dog.prototype.numLegs = 4;",
- "",
- "let beagle = new Dog(\"Snoopy\");",
- "",
- "let ownProps = [];",
- "let prototypeProps = [];",
- "",
- "// Add your code below this line ",
- "",
- "",
- ""
- ],
- "tests": [
- "assert(ownProps.indexOf('name') !== -1, 'message: The ownProps
array should include \"name\"
.');",
- "assert(prototypeProps.indexOf('numLegs') !== -1, 'message: The prototypeProps
array should include \"numLegs\"
.');",
- "assert(!/\\Object.keys/.test(code), 'message: Solve this challenge without using the built in method Object.keys()
.');"
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name;\n}\n\nDog.prototype.numLegs = 4;\n\nlet beagle = new Dog(\"Snoopy\");\n\nlet ownProps = [];\nlet prototypeProps = [];\nfor (let prop in beagle) {\n if (beagle.hasOwnProperty(prop)) {\n ownProps.push(prop);\n } else {\n prototypeProps.push(prop);\n }\n}"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daf367417b2b2512b7e",
- "title": "Understand the Constructor Property",
- "description": [
- "There is a special constructor
property located on the object instances duck
and beagle
that were created in the previous challenges:",
- "let duck = new Bird();
",
- "Note that the
let beagle = new Dog();
console.log(duck.constructor === Bird); //prints true
console.log(beagle.constructor === Dog); //prints trueconstructor
property is a reference to the constructor function that created the instance.",
- "The advantage of the constructor
property is that it's possible to check for this property to find out what kind of object it is. Here's an example of how this could be used:",
- "function joinBirdFraternity(candidate) {
",
- "Note
if (candidate.constructor === Bird) {
return true;
} else {
return false;
}
}
Since the constructor
property can be overwritten (which will be covered in the next two challenges) it’s generally better to use the instanceof
method to check the type of an object.",
- "
",
- "Write a joinDogFraternity
function that takes a candidate
parameter and, using the constructor
property, return true
if the candidate is a Dog
, otherwise return false
."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name;",
- "}",
- "",
- "// Add your code below this line",
- "function joinDogFraternity(candidate) {",
- " ",
- "}",
- ""
- ],
- "tests": [
- "assert(typeof(joinDogFraternity) === 'function', 'message: joinDogFraternity
should be defined as a function.');",
- "assert(joinDogFraternity(new Dog(\"\")) === true, 'message: joinDogFraternity
should return true ifcandidate
is an instance of Dog
.');",
- "assert(/\\.constructor/.test(code) && !/instanceof/.test(code), 'message: joinDogFraternity
should use the constructor
property.');"
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name;\n}\nfunction joinDogFraternity(candidate) {\n return candidate.constructor === Dog;\n}"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daf367417b2b2512b7f",
- "title": "Change the Prototype to a New Object",
- "description": [
- "Up until now you have been adding properties to the prototype
individually:",
- "Bird.prototype.numLegs = 2;
",
- "This becomes tedious after more than a few properties.",
- "Bird.prototype.eat = function() {
",
- "A more efficient way is to set the
console.log(\"nom nom nom\");
}
Bird.prototype.describe = function() {
console.log(\"My name is \" + this.name);
}prototype
to a new object that already contains the properties. This way, the properties are added all at once:",
- "Bird.prototype = {
",
- "
numLegs: 2,
eat: function() {
console.log(\"nom nom nom\");
},
describe: function() {
console.log(\"My name is \" + this.name);
}
};
",
- "Add the property numLegs
and the two methods eat()
and describe()
to the prototype
of Dog
by setting the prototype
to a new object."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name; ",
- "}",
- "",
- "Dog.prototype = {",
- " // Add your code below this line",
- " ",
- "};"
- ],
- "tests": [
- "assert((/Dog\\.prototype\\s*?=\\s*?{/).test(code), 'message: Dog.prototype
should be set to a new object.');",
- "assert(Dog.prototype.numLegs !== undefined, 'message: Dog.prototype
should have the property numLegs
.');",
- "assert(typeof Dog.prototype.eat === 'function', 'message: Dog.prototype
should have the method eat()
.'); ",
- "assert(typeof Dog.prototype.describe === 'function', 'message: Dog.prototype
should have the method describe()
.'); "
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name; \n}\nDog.prototype = {\nnumLegs: 4,\n eat () {\n console.log('nom nom nom');\n },\n describe () {\n console.log('My name is ' + this.name);\n }\n};"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7daf367417b2b2512b80",
- "title": "Remember to Set the Constructor Property when Changing the Prototype",
- "description": [
- "There is one crucial side effect of manually setting the prototype
to a new object. It erased the constructor
property! The code in the previous challenge would print the following for duck
:",
- "console.log(duck.constructor)
",
- "To fix this, whenever a prototype is manually set to a new object, remember to define the
// prints ‘undefined’ - Oops!constructor
property:",
- "Bird.prototype = {
",
- "
constructor: Bird, // define the constructor property
numLegs: 2,
eat: function() {
console.log(\"nom nom nom\");
},
describe: function() {
console.log(\"My name is \" + this.name);
}
};
",
- "Define the constructor
property on the Dog
prototype
."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name; ",
- "}",
- "",
- "// Modify the code below this line",
- "Dog.prototype = {",
- " ",
- " numLegs: 2, ",
- " eat: function() {",
- " console.log(\"nom nom nom\"); ",
- " }, ",
- " describe: function() {",
- " console.log(\"My name is \" + this.name); ",
- " }",
- "};"
- ],
- "tests": [
- "assert(Dog.prototype.constructor === Dog, 'message: Dog.prototype
should set the constructor
property.');"
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name; \n}\nDog.prototype = {\n constructor: Dog,\n numLegs: 2, \n eat: function() {\n console.log(\"nom nom nom\"); \n }, \n describe: function() {\n console.log(\"My name is \" + this.name); \n }\n};"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db0367417b2b2512b81",
- "title": "Understand Where an Object’s Prototype Comes From",
- "description": [
- "Just like people inherit genes from their parents, an object inherits its prototype
directly from the constructor function that created it. For example, here the Bird
constructor creates the duck
object:",
- "function Bird(name) {
",
- "
this.name = name;
}
let duck = new Bird(\"Donald\");duck
inherits its prototype
from the Bird
constructor function. You can show this relationship with the isPrototypeOf
method:",
- "Bird.prototype.isPrototypeOf(duck);
",
- "
// returns true
",
- "Use isPrototypeOf
to check the prototype
of beagle
."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name;",
- "}",
- "",
- "let beagle = new Dog(\"Snoopy\");",
- "",
- "// Add your code below this line",
- "",
- ""
- ],
- "tests": [
- "assert(/Dog\\.prototype\\.isPrototypeOf\\(beagle\\)/.test(code), 'message: Show that Dog.prototype
is the prototype
of beagle
');"
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name;\n}\nlet beagle = new Dog(\"Snoopy\");\nDog.prototype.isPrototypeOf(beagle);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db0367417b2b2512b82",
- "title": "Understand the Prototype Chain",
- "description": [
- "All objects in JavaScript (with a few exceptions) have a prototype
. Also, an object’s prototype
itself is an object.",
- "function Bird(name) {
",
- "Because a
this.name = name;
}
typeof Bird.prototype; // => objectprototype
is an object, a prototype
can have its own prototype
! In this case, the prototype
of Bird.prototype
is Object.prototype
:",
- "Object.prototype.isPrototypeOf(Bird.prototype);
",
- "How is this useful? You may recall the
// returns truehasOwnProperty
method from a previous challenge:",
- "let duck = new Bird(\"Donald\");
",
- "The
duck.hasOwnProperty(\"name\"); // => truehasOwnProperty
method is defined in Object.prototype
, which can be accessed by Bird.prototype
, which can then be accessed by duck
. This is an example of the prototype
chain.",
- "In this prototype
chain, Bird
is the supertype
for duck
, while duck
is the subtype
. Object
is a supertype
for both Bird
and duck
.",
- "Object
is a supertype
for all objects in JavaScript. Therefore, any object can use the hasOwnProperty
method.",
- "
",
- "Modify the code to show the correct prototype chain."
- ],
- "challengeSeed": [
- "function Dog(name) {",
- " this.name = name;",
- "}",
- "",
- "let beagle = new Dog(\"Snoopy\");",
- "",
- "Dog.prototype.isPrototypeOf(beagle); // => true",
- "",
- "// Fix the code below so that it evaluates to true",
- "???.isPrototypeOf(Dog.prototype);",
- ""
- ],
- "tests": [
- "assert(/Object\\.prototype\\.isPrototypeOf/.test(code), \"message: Your code should show that Object.prototype
is the prototype of Dog.prototype
\");"
- ],
- "solutions": [
- "function Dog(name) {\n this.name = name;\n}\nlet beagle = new Dog(\"Snoopy\");\nDog.prototype.isPrototypeOf(beagle);\nObject.prototype.isPrototypeOf(Dog.prototype);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db0367417b2b2512b83",
- "title": "Use Inheritance So You Don't Repeat Yourself",
- "description": [
- "There's a principle in programming called Don't Repeat Yourself (DRY)
. The reason repeated code is a problem is because any change requires fixing code in multiple places. This usually means more work for programmers and more room for errors.",
- "Notice in the example below that the describe
method is shared by Bird
and Dog
:",
- "Bird.prototype = {
",
- "The
constructor: Bird,
describe: function() {
console.log(\"My name is \" + this.name);
}
};
Dog.prototype = {
constructor: Dog,
describe: function() {
console.log(\"My name is \" + this.name);
}
};describe
method is repeated in two places. The code can be edited to follow the DRY
principle by creating a supertype
(or parent) called Animal
:",
- "function Animal() { };
",
- "Since
Animal.prototype = {
constructor: Animal,
describe: function() {
console.log(\"My name is \" + this.name);
}
};Animal
includes the describe
method, you can remove it from Bird
and Dog
:",
- "Bird.prototype = {
",
- "
constructor: Bird
};
Dog.prototype = {
constructor: Dog
};
",
- "The eat
method is repeated in both Cat
and Bear
. Edit the code in the spirit of DRY
by moving the eat
method to the Animal
supertype
."
- ],
- "challengeSeed": [
- "function Cat(name) {",
- " this.name = name; ",
- "}",
- "",
- "Cat.prototype = {",
- " constructor: Cat, ",
- " eat: function() {",
- " console.log(\"nom nom nom\");",
- " }",
- "};",
- "",
- "function Bear(name) {",
- " this.name = name; ",
- "}",
- "",
- "Bear.prototype = {",
- " constructor: Bear, ",
- " eat: function() {",
- " console.log(\"nom nom nom\");",
- " }",
- "};",
- "",
- "function Animal() { }",
- "",
- "Animal.prototype = {",
- " constructor: Animal,",
- " ",
- "};"
- ],
- "tests": [
- "assert(Animal.prototype.hasOwnProperty('eat'), 'message: Animal.prototype
should have the eat
property.');",
- "assert(!(Bear.prototype.hasOwnProperty('eat')), 'message: Bear.prototype
should not have the eat
property.');",
- "assert(!(Cat.prototype.hasOwnProperty('eat')), 'message: Cat.prototype
should not have the eat
property.');"
- ],
- "solutions": [
- "function Cat(name) {\n this.name = name; \n}\n\nCat.prototype = {\n constructor: Cat\n};\n\nfunction Bear(name) {\n this.name = name; \n}\n\nBear.prototype = {\n constructor: Bear\n};\n\nfunction Animal() { }\n\nAnimal.prototype = {\n constructor: Animal,\n eat: function() {\n console.log(\"nom nom nom\");\n }\n};"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db0367417b2b2512b84",
- "title": "Inherit Behaviors from a Supertype",
- "description": [
- "In the previous challenge, you created a supertype
called Animal
that defined behaviors shared by all animals:",
- "function Animal() { }
",
- "This and the next challenge will cover how to reuse
Animal.prototype.eat = function() {
console.log(\"nom nom nom\");
};Animal's
methods inside Bird
and Dog
without defining them again. It uses a technique called inheritance
.",
- "This challenge covers the first step: make an instance of the supertype
(or parent).",
- "You already know one way to create an instance of Animal
using the new
operator:",
- "let animal = new Animal();
",
- "There are some disadvantages when using this syntax for inheritance
, which are too complex for the scope of this challenge. Instead, here's an alternative approach without those disadvantages:",
- "let animal = Object.create(Animal.prototype);
",
- "Object.create(obj)
creates a new object, and sets obj
as the new object's prototype
. Recall that the prototype
is like the \"recipe\" for creating an object. By setting the prototype
of animal
to be Animal's
prototype
, you are effectively giving the animal
instance the same \"recipe\" as any other instance of Animal
.",
- "animal.eat(); // prints \"nom nom nom\"
",
- "
animal instanceof Animal; // => true
",
- "Use Object.create
to make two instances of Animal
named duck
and beagle
."
- ],
- "challengeSeed": [
- "function Animal() { }",
- "",
- "Animal.prototype = {",
- " constructor: Animal, ",
- " eat: function() {",
- " console.log(\"nom nom nom\");",
- " }",
- "};",
- "",
- "// Add your code below this line",
- "",
- "let duck; // Change this line",
- "let beagle; // Change this line",
- "",
- "duck.eat(); // Should print \"nom nom nom\"",
- "beagle.eat(); // Should print \"nom nom nom\" "
- ],
- "tests": [
- "assert(typeof duck !== \"undefined\", 'message: The duck
variable should be defined.');",
- "assert(typeof beagle !== \"undefined\", 'message: The beagle
variable should be defined.');",
- "assert(duck instanceof Animal, 'message: duck
should have a prototype
of Animal
.');",
- "assert(beagle instanceof Animal, 'message: beagle
should have a prototype
of Animal
.');"
- ],
- "solutions": [
- "function Animal() { }\n\nAnimal.prototype = {\n constructor: Animal, \n eat: function() {\n console.log(\"nom nom nom\");\n }\n};\nlet duck = Object.create(Animal.prototype);\nlet beagle = Object.create(Animal.prototype);\n\nduck.eat();\nbeagle.eat();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db1367417b2b2512b85",
- "title": "Set the Child's Prototype to an Instance of the Parent",
- "description": [
- "In the previous challenge you saw the first step for inheriting behavior from the supertype
(or parent) Animal
: making a new instance of Animal
.",
- "This challenge covers the next step: set the prototype
of the subtype
(or child)—in this case, Bird
—to be an instance of Animal
.",
- "Bird.prototype = Object.create(Animal.prototype);
",
- "Remember that the prototype
is like the \"recipe\" for creating an object. In a way, the recipe for Bird
now includes all the key \"ingredients\" from Animal
.",
- "let duck = new Bird(\"Donald\");
",
- "
duck.eat(); // prints \"nom nom nom\"duck
inherits all of Animal
's properties, including the eat
method.",
- "
",
- "Modify the code so that instances of Dog
inherit from Animal
."
- ],
- "challengeSeed": [
- "function Animal() { }",
- "",
- "Animal.prototype = {",
- " constructor: Animal,",
- " eat: function() {",
- " console.log(\"nom nom nom\");",
- " }",
- "};",
- "",
- "function Dog() { }",
- "",
- "// Add your code below this line",
- "",
- "",
- "let beagle = new Dog();",
- "beagle.eat(); // Should print \"nom nom nom\""
- ],
- "tests": [
- "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype
should be an instance of Animal
.');"
- ],
- "solutions": [
- "function Animal() { }\n\nAnimal.prototype = {\n constructor: Animal,\n eat: function() {\n console.log(\"nom nom nom\");\n }\n};\n\nfunction Dog() { }\nDog.prototype = Object.create(Animal.prototype);\n\nlet beagle = new Dog();\nbeagle.eat();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db1367417b2b2512b86",
- "title": "Reset an Inherited Constructor Property",
- "description": [
- "When an object inherits its prototype
from another object, it also inherits the supertype
's constructor property.",
- "Here's an example:",
- "function Bird() { }
",
- "But
Bird.prototype = Object.create(Animal.prototype);
let duck = new Bird();
duck.constructor // function Animal(){...}duck
and all instances of Bird
should show that they were constructed by Bird
and not Animal
. To do so, you can manually set Bird's
constructor property to the Bird
object:",
- "Bird.prototype.constructor = Bird;
",
- "
duck.constructor // function Bird(){...}
",
- "Fix the code so duck.constructor
and beagle.constructor
return their respective constructors."
- ],
- "challengeSeed": [
- "function Animal() { }",
- "function Bird() { }",
- "function Dog() { }",
- "",
- "Bird.prototype = Object.create(Animal.prototype);",
- "Dog.prototype = Object.create(Animal.prototype);",
- "",
- "// Add your code below this line",
- "",
- "",
- "",
- "let duck = new Bird();",
- "let beagle = new Dog();"
- ],
- "tests": [
- "assert(Animal.prototype.isPrototypeOf(Bird.prototype), 'message: Bird.prototype
should be an instance of Animal
.');",
- "assert(duck.constructor === Bird, 'message: duck.constructor
should return Bird
.');",
- "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype
should be an instance of Animal
.');",
- "assert(beagle.constructor === Dog, 'message: beagle.constructor
should return Dog
.');"
- ],
- "solutions": [
- "function Animal() { }\nfunction Bird() { }\nfunction Dog() { }\nBird.prototype = Object.create(Animal.prototype);\nDog.prototype = Object.create(Animal.prototype);\nDog.prototype.constructor = Dog;\nBird.prototype.constructor = Bird;\nlet duck = new Bird();\nlet beagle = new Dog();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db1367417b2b2512b87",
- "title": "Add Methods After Inheritance",
- "description": [
- "A constructor function that inherits its prototype
object from a supertype
constructor function can still have its own methods in addition to inherited methods.",
- "For example, Bird
is a constructor that inherits its prototype
from Animal
:",
- "function Animal() { }
",
- "In addition to what is inherited from
Animal.prototype.eat = function() {
console.log(\"nom nom nom\");
};
function Bird() { }
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;Animal
, you want to add behavior that is unique to Bird
objects. Here, Bird
will get a fly()
function. Functions are added to Bird's
prototype
the same way as any constructor function:",
- "Bird.prototype.fly = function() {
",
- "Now instances of
console.log(\"I'm flying!\");
};Bird
will have both eat()
and fly()
methods:",
- "let duck = new Bird();
",
- "
duck.eat(); // prints \"nom nom nom\"
duck.fly(); // prints \"I'm flying!\"
",
- "Add all necessary code so the Dog
object inherits from Animal
and the Dog's
prototype
constructor is set to Dog. Then add a bark()
method to the Dog
object so that beagle
can both eat()
and bark()
. The bark()
method should print \"Woof!\" to the console."
- ],
- "challengeSeed": [
- "function Animal() { }",
- "Animal.prototype.eat = function() { console.log(\"nom nom nom\"); };",
- "",
- "function Dog() { }",
- "",
- "// Add your code below this line",
- "",
- "",
- "",
- "",
- "// Add your code above this line",
- "",
- "let beagle = new Dog();",
- "",
- "beagle.eat(); // Should print \"nom nom nom\"",
- "beagle.bark(); // Should print \"Woof!\""
- ],
- "tests": [
- "assert(typeof Animal.prototype.bark == \"undefined\", 'message: Animal
should not respond to the bark()
method.');",
- "assert(typeof Dog.prototype.eat == \"function\", 'message: Dog
should inherit the eat()
method from Animal
.');",
- "assert(Dog.prototype.hasOwnProperty('bark'), 'message: Dog
should have the bark()
method as an own
property.');",
- "assert(beagle instanceof Animal, 'message: beagle
should be an instanceof
Animal
.');",
- "assert(beagle.constructor === Dog, 'message: The constructor for beagle
should be set to Dog
.');"
- ],
- "solutions": [
- "function Animal() { }\nAnimal.prototype.eat = function() { console.log(\"nom nom nom\"); };\n\nfunction Dog() { }\nDog.prototype = Object.create(Animal.prototype);\nDog.prototype.constructor = Dog;\nDog.prototype.bark = function () {\n console.log('Woof!');\n};\nlet beagle = new Dog();\n\nbeagle.eat();\nbeagle.bark();"
- ],
- "hints": [
- "Objects inherit methods from other objects by cloning their prototype. The Object.create method will come in handy, and don't forget to reset the constructor property afterward!"
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db1367417b2b2512b88",
- "title": "Override Inherited Methods",
- "description": [
- "In previous lessons, you learned that an object can inherit its behavior (methods) from another object by cloning its prototype
object:",
- "ChildObject.prototype = Object.create(ParentObject.prototype);
",
- "Then the ChildObject
received its own methods by chaining them onto its prototype
:",
- "ChildObject.prototype.methodName = function() {...};
",
- "It's possible to override an inherited method. It's done the same way - by adding a method to ChildObject.prototype
using the same method name as the one to override.",
- "Here's an example of Bird
overriding the eat()
method inherited from Animal
:",
- "function Animal() { }
",
- "If you have an instance
Animal.prototype.eat = function() {
return \"nom nom nom\";
};
function Bird() { }
// Inherit all methods from Animal
Bird.prototype = Object.create(Animal.prototype);
// Bird.eat() overrides Animal.eat()
Bird.prototype.eat = function() {
return \"peck peck peck\";
};let duck = new Bird();
and you call duck.eat()
, this is how JavaScript looks for the method on duck’s
prototype
chain:",
- "1. duck => Is eat() defined here? No.",
- "2. Bird => Is eat() defined here? => Yes. Execute it and stop searching.",
- "3. Animal => eat() is also defined, but JavaScript stopped searching before reaching this level.",
- "4. Object => JavaScript stopped searching before reaching this level.",
- "
",
- "Override the fly()
method for Penguin
so that it returns \"Alas, this is a flightless bird.\""
- ],
- "challengeSeed": [
- "function Bird() { }",
- "",
- "Bird.prototype.fly = function() { return \"I am flying!\"; };",
- "",
- "function Penguin() { }",
- "Penguin.prototype = Object.create(Bird.prototype);",
- "Penguin.prototype.constructor = Penguin;",
- "",
- "// Add your code below this line",
- "",
- "",
- "",
- "// Add your code above this line",
- "",
- "let penguin = new Penguin();",
- "console.log(penguin.fly());"
- ],
- "tests": [
- "assert(penguin.fly() === \"Alas, this is a flightless bird.\", 'message: penguin.fly()
should return the string \"Alas, this is a flightless bird.\"');",
- "assert((new Bird()).fly() === \"I am flying!\", 'message: The bird.fly()
method should return \"I am flying!\"');"
- ],
- "solutions": [
- "function Bird() { }\n\nBird.prototype.fly = function() { return \"I am flying!\"; };\n\nfunction Penguin() { }\nPenguin.prototype = Object.create(Bird.prototype);\nPenguin.prototype.constructor = Penguin;\nPenguin.prototype.fly = () => 'Alas, this is a flightless bird.';\nlet penguin = new Penguin();\nconsole.log(penguin.fly());"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db2367417b2b2512b89",
- "title": "Use a Mixin to Add Common Behavior Between Unrelated Objects",
- "description": [
- "As you have seen, behavior is shared through inheritance. However, there are cases when inheritance is not the best solution. Inheritance does not work well for unrelated objects like Bird
and Airplane
. They can both fly, but a Bird
is not a type of Airplane
and vice versa.",
- "For unrelated objects, it's better to use mixins
. A mixin
allows other objects to use a collection of functions.",
- "let flyMixin = function(obj) {
",
- "The
obj.fly = function() {
console.log(\"Flying, wooosh!\");
}
};flyMixin
takes any object and gives it the fly
method.",
- "let bird = {
",
- "Here
name: \"Donald\",
numLegs: 2
};
let plane = {
model: \"777\",
numPassengers: 524
};
flyMixin(bird);
flyMixin(plane);bird
and plane
are passed into flyMixin
, which then assigns the fly
function to each object. Now bird
and plane
can both fly:",
- "bird.fly(); // prints \"Flying, wooosh!\"
",
- "Note how the
plane.fly(); // prints \"Flying, wooosh!\"mixin
allows for the same fly
method to be reused by unrelated objects bird
and plane
.",
- "
",
- "Create a mixin
named glideMixin
that defines a method named glide
. Then use the glideMixin
to give both bird
and boat
the ability to glide."
- ],
- "challengeSeed": [
- "let bird = {",
- " name: \"Donald\",",
- " numLegs: 2",
- "};",
- "",
- "let boat = {",
- " name: \"Warrior\",",
- " type: \"race-boat\"",
- "};",
- "",
- "// Add your code below this line",
- "",
- "",
- "",
- "",
- "",
- ""
- ],
- "tests": [
- "assert(typeof glideMixin === \"function\", 'message: Your code should declare a glideMixin
variable that is a function.');",
- "assert(typeof bird.glide === \"function\", 'message: Your code should use the glideMixin
on the bird
object to give it the glide
method.');",
- "assert(typeof boat.glide === \"function\", 'message: Your code should use the glideMixin
on the boat
object to give it the glide
method.');"
- ],
- "solutions": [
- "let bird = {\n name: \"Donald\",\n numLegs: 2\n};\n\nlet boat = {\n name: \"Warrior\",\n type: \"race-boat\"\n};\nfunction glideMixin (obj) {\n obj.glide = () => 'Gliding!';\n}\n\nglideMixin(bird);\nglideMixin(boat);"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db2367417b2b2512b8a",
- "title": "Use Closure to Protect Properties Within an Object from Being Modified Externally",
- "description": [
- "In the previous challenge, bird
had a public property name
. It is considered public because it can be accessed and changed outside of bird
's definition.",
- "bird.name = \"Duffy\";
",
- "Therefore, any part of your code can easily change the name of bird
to any value. Think about things like passwords and bank accounts being easily changeable by any part of your codebase. That could cause a lot of issues.",
- "The simplest way to make properties private is by creating a variable within the constructor function. This changes the scope of that variable to be within the constructor function versus available globally. This way, the property can only be accessed and changed by methods also within the constructor function.",
- "function Bird() {
",
- "Here
let hatchedEgg = 10; // private property
this.getHatchedEggCount = function() { // publicly available method that a bird object can use
return hatchedEgg;
};
}
let ducky = new Bird();
ducky.getHatchedEggCount(); // returns 10getHachedEggCount
is a privileged method, because it has access to the private variable hatchedEgg
. This is possible because hatchedEgg
is declared in the same context as getHachedEggCount
. In JavaScript, a function always has access to the context in which it was created. This is called closure
.",
- "
",
- "Change how weight
is declared in the Bird
function so it is a private variable. Then, create a method getWeight
that returns the value of weight
."
- ],
- "challengeSeed": [
- "function Bird() {",
- " this.weight = 15;",
- " ",
- " ",
- "}",
- ""
- ],
- "tests": [
- "assert(!code.match(/this\\.weight/g), 'message: The weight
property should be a private variable.');",
- "assert((new Bird()).getWeight() === 15, 'message: Your code should create a method in Bird
called getWeight
that returns the weight
.');"
- ],
- "solutions": [
- "function Bird() {\n let weight = 15;\n \n this.getWeight = () => weight;\n}"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db2367417b2b2512b8b",
- "title": "Understand the Immediately Invoked Function Expression (IIFE)",
- "description": [
- "A common pattern in JavaScript is to execute a function as soon as it is declared:",
- "(function () {
",
- "Note that the function has no name and is not stored in a variable. The two parentheses () at the end of the function expression cause it to be immediately executed or invoked. This pattern is known as an
console.log(\"Chirp, chirp!\");
})(); // this is an anonymous function expression that executes right away
// Outputs \"Chirp, chirp!\" immediatelyimmediately invoked function expression
or IIFE
.",
- "
",
- "Rewrite the function makeNest
and remove its call so instead it's an anonymous immediately invoked function expression
(IIFE
)."
- ],
- "challengeSeed": [
- "function makeNest() {",
- " console.log(\"A cozy nest is ready\");",
- "}",
- "",
- "makeNest(); "
- ],
- "tests": [
- "assert(/\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?{/.test(code), 'message: The function should be anonymous.');",
- "assert(/}\\s*?\\)\\s*?\\(\\s*?\\)/.test(code), 'message: Your function should have parentheses at the end of the expression to call it immediately.');"
- ],
- "solutions": [
- "(function () {\n console.log(\"A cozy nest is ready\");\n})();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db2367417b2b2512b8c",
- "title": "Use an IIFE to Create a Module",
- "description": [
- "An immediately invoked function expression
(IIFE
) is often used to group related functionality into a single object or module
. For example, an earlier challenge defined two mixins:",
- "function glideMixin(obj) {
",
- "We can group these
obj.glide = function() {
console.log(\"Gliding on the water\");
};
}
function flyMixin(obj) {
obj.fly = function() {
console.log(\"Flying, wooosh!\");
};
}mixins
into a module as follows:",
- "let motionModule = (function () {
",
- "Note that you have an
return {
glideMixin: function (obj) {
obj.glide = function() {
console.log(\"Gliding on the water\");
};
},
flyMixin: function(obj) {
obj.fly = function() {
console.log(\"Flying, wooosh!\");
};
}
}
}) (); // The two parentheses cause the function to be immediately invokedimmediately invoked function expression
(IIFE
) that returns an object motionModule
. This returned object contains all of the mixin
behaviors as properties of the object.",
- "The advantage of the module
pattern is that all of the motion behaviors can be packaged into a single object that can then be used by other parts of your code. Here is an example using it:",
- "motionModule.glideMixin(duck);
",
- "
duck.glide();
",
- "Create a module
named funModule
to wrap the two mixins
isCuteMixin
and singMixin
. funModule
should return an object."
- ],
- "challengeSeed": [
- "let isCuteMixin = function(obj) {",
- " obj.isCute = function() {",
- " return true;",
- " };",
- "};",
- "let singMixin = function(obj) {",
- " obj.sing = function() {",
- " console.log(\"Singing to an awesome tune\");",
- " };",
- "};"
- ],
- "tests": [
- "assert(typeof funModule === \"object\", 'message: funModule
should be defined and return an object.');",
- "assert(typeof funModule.isCuteMixin === \"function\", 'message: funModule.isCuteMixin
should access a function.');",
- "assert(typeof funModule.singMixin === \"function\", 'message: funModule.singMixin
should access a function.');"
- ],
- "solutions": [
- "const funModule = (function () {\n return {\n isCuteMixin: obj => {\n obj.isCute = () => true;\n },\n singMixin: obj => {\n obj.sing = () => console.log(\"Singing to an awesome tune\");\n }\n };\n})();"
- ],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json
deleted file mode 100644
index 56e34f93bb..0000000000
--- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json
+++ /dev/null
@@ -1,994 +0,0 @@
-{
- "name": "Regular Expressions",
- "order": 3,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7db3367417b2b2512b8d",
- "title": "Introduction to the Regular Expression Challenges",
- "description": [
- "",
- "",
- "Regular expressions are special strings that represent a search pattern. Also known as \"regex\" or \"regexp\", they help programmers match, search, and replace text. Regular expressions can appear cryptic because a few characters have special meaning. The goal is to combine the symbols and text into a pattern that matches what you want, but only what you want. This section will cover the characters, a few shortcuts, and the common uses for writing regular expressions.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "587d7db3367417b2b2512b8e",
- "title": "Using the Test Method",
- "description": [
- "Regular expressions are used in programming languages to match parts of strings. You create patterns to help you do that matching.",
- "If you want to find the word \"the\"
in the string \"The dog chased the cat\"
, you could use the following regular expression: /the/
. Notice that quote marks are not required within the regular expression.",
- "JavaScript has multiple ways to use regexes. One way to test a regex is using the .test()
method. The .test()
method takes the regex, applies it to a string (which is placed inside the parentheses), and returns true
or false
if your pattern finds something or not.",
- "let testStr = \"freeCodeCamp\";
",
- "
let testRegex = /Code/;
testRegex.test(testStr);
// Returns true
",
- "Apply the regex myRegex
on the string myString
using the .test()
method."
- ],
- "challengeSeed": [
- "let myString = \"Hello, World!\";",
- "let myRegex = /Hello/;",
- "let result = myRegex; // Change this line"
- ],
- "tests": [
- "assert(code.match(/myRegex.test\\(\\s*myString\\s*\\)/), 'message: You should use .test()
to test the regex.');",
- "assert(result === true, 'message: Your result should return true
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db3367417b2b2512b8f",
- "title": "Match Literal Strings",
- "description": [
- "In the last challenge, you searched for the word \"Hello\"
using the regular expression /Hello/
. That regex searched for a literal match of the string \"Hello\"
. Here's another example searching for a literal match of the string \"Kevin\"
:",
- "let testStr = \"Hello, my name is Kevin.\";
",
- "Any other forms of
let testRegex = /Kevin/;
testRegex.test(testStr);
// Returns true\"Kevin\"
will not match. For example, the regex /Kevin/
will not match \"kevin\"
or \"KEVIN\"
.",
- "let wrongRegex = /kevin/;
",
- "A future challenge will show how to match those other forms as well.",
- "
wrongRegex.test(testStr);
// Returns false
",
- "Complete the regex waldoRegex
to find \"Waldo\"
in the string waldoIsHiding
with a literal match."
- ],
- "challengeSeed": [
- "let waldoIsHiding = \"Somewhere Waldo is hiding in this text.\";",
- "let waldoRegex = /search/; // Change this line",
- "let result = waldoRegex.test(waldoIsHiding);"
- ],
- "tests": [
- "assert(waldoRegex.test(waldoIsHiding), 'message: Your regex waldoRegex
should find \"Waldo\"
');",
- "assert(!waldoRegex.test('Somewhere is hiding in this text.'), 'message: Your regex waldoRegex
should not search for anything else.');",
- "assert(!/\\/.*\\/i/.test(code), 'message: You should perform a literal string match with your regex.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db4367417b2b2512b90",
- "title": "Match a Literal String with Different Possibilities",
- "description": [
- "Using regexes like /coding/
, you can look for the pattern \"coding\"
in another string.",
- "This is powerful to search single strings, but it's limited to only one pattern. You can search for multiple patterns using the alternation
or OR
operator: |
.",
- "This operator matches patterns either before or after it. For example, if you wanted to match \"yes\"
or \"no\"
, the regex you want is /yes|no/
.",
- "You can also search for more than just two patterns. You can do this by adding more patterns with more OR
operators separating them, like /yes|no|maybe/
.",
- "
",
- "Complete the regex petRegex
to match the pets \"dog\"
, \"cat\"
, \"bird\"
, or \"fish\"
."
- ],
- "challengeSeed": [
- "let petString = \"James has a pet cat.\";",
- "let petRegex = /change/; // Change this line",
- "let result = petRegex.test(petString);"
- ],
- "tests": [
- "assert(petRegex.test('John has a pet dog.'), 'message: Your regex petRegex
should return true
for the string \"John has a pet dog.\"
');",
- "assert(!petRegex.test('Emma has a pet rock.'), 'message: Your regex petRegex
should return false
for the string \"Emma has a pet rock.\"
');",
- "assert(petRegex.test('Emma has a pet bird.'), 'message: Your regex petRegex
should return true
for the string \"Emma has a pet bird.\"
');",
- "assert(petRegex.test('Liz has a pet cat.'), 'message: Your regex petRegex
should return true
for the string \"Liz has a pet cat.\"
');",
- "assert(!petRegex.test('Kara has a pet dolphin.'), 'message: Your regex petRegex
should return false
for the string \"Kara has a pet dolphin.\"
');",
- "assert(petRegex.test('Alice has a pet fish.'), 'message: Your regex petRegex
should return true
for the string \"Alice has a pet fish.\"
');",
- "assert(!petRegex.test('Jimmy has a pet computer.'), 'message: Your regex petRegex
should return false
for the string \"Jimmy has a pet computer.\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db4367417b2b2512b91",
- "title": "Ignore Case While Matching",
- "description": [
- "Up until now, you've looked at regexes to do literal matches of strings. But sometimes, you might want to also match case differences.",
- "Case (or sometimes letter case) is the difference between uppercase letters and lowercase letters. Examples of uppercase are \"A\"
, \"B\"
, and \"C\"
. Examples of lowercase are \"a\"
, \"b\"
, and \"c\"
.",
- "You can match both cases using what is called a flag. There are other flags but here you'll focus on the flag that ignores case - the i
flag. You can use it by appending it to the regex. An example of using this flag is /ignorecase/i
. This regex can match the strings \"ignorecase\"
, \"igNoreCase\"
, and \"IgnoreCase\"
.",
- "
",
- "Write a regex fccRegex
to match \"freeCodeCamp\"
, no matter its case. Your regex should not match any abbreviations or variations with spaces."
- ],
- "challengeSeed": [
- "let myString = \"freeCodeCamp\";",
- "let fccRegex = /change/; // Change this line",
- "let result = fccRegex.test(myString);"
- ],
- "tests": [
- "assert(fccRegex.test('freeCodeCamp'), 'message: Your regex should match freeCodeCamp
');",
- "assert(fccRegex.test('FreeCodeCamp'), 'message: Your regex should match FreeCodeCamp
');",
- "assert(fccRegex.test('FreecodeCamp'), 'message: Your regex should match FreecodeCamp
');",
- "assert(fccRegex.test('FreeCodecamp'), 'message: Your regex should match FreeCodecamp
');",
- "assert(!fccRegex.test('Free Code Camp'), 'message: Your regex should not match Free Code Camp
');",
- "assert(fccRegex.test('FreeCOdeCamp'), 'message: Your regex should match FreeCOdeCamp
');",
- "assert(!fccRegex.test('FCC'), 'message: Your regex should not match FCC
');",
- "assert(fccRegex.test('FrEeCoDeCamp'), 'message: Your regex should match FrEeCoDeCamp
');",
- "assert(fccRegex.test('FrEeCodECamp'), 'message: Your regex should match FrEeCodECamp
');",
- "assert(fccRegex.test('FReeCodeCAmp'), 'message: Your regex should match FReeCodeCAmp
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db4367417b2b2512b92",
- "title": "Extract Matches",
- "description": [
- "So far, you have only been checking if a pattern exists or not within a string. You can also extract the actual matches you found with the .match()
method.",
- "To use the .match()
method, apply the method on a string and pass in the regex inside the parentheses. Here's an example:",
- "\"Hello, World!\".match(/Hello/);
",
- "
// Returns [\"Hello\"]
let ourStr = \"Regular expressions\";
let ourRegex = /expressions/;
ourStr.match(ourRegex);
// Returns [\"expressions\"]
",
- "Apply the .match()
method to extract the word coding
."
- ],
- "challengeSeed": [
- "let extractStr = \"Extract the word 'coding' from this string.\";",
- "let codingRegex = /change/; // Change this line",
- "let result = extractStr; // Change this line"
- ],
- "tests": [
- "assert(result.join() === \"coding\", 'message: The result
should have the word coding
');",
- "assert(codingRegex.source === \"coding\", 'message: Your regex codingRegex
should search for coding
');",
- "assert(code.match(/\\.match\\(.*\\)/), 'message: You should use the .match()
method.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db4367417b2b2512b93",
- "title": "Find More Than the First Match",
- "description": [
- "So far, you have only been able to extract or search a pattern once.",
- "let testStr = \"Repeat, Repeat, Repeat\";
",
- "To search or extract a pattern more than once, you can use the
let ourRegex = /Repeat/;
testStr.match(ourRegex);
// Returns [\"Repeat\"]g
flag.",
- "let repeatRegex = /Repeat/g;
",
- "
testStr.match(repeatRegex);
// Returns [\"Repeat\", \"Repeat\", \"Repeat\"]
",
- "Using the regex starRegex
, find and extract both \"Twinkle\"
words from the string twinkleStar
.",
- "Note
You can have multiple flags on your regex like /search/gi
"
- ],
- "challengeSeed": [
- "let twinkleStar = \"Twinkle, twinkle, little star\";",
- "let starRegex = /change/; // Change this line",
- "let result = twinkleStar; // Change this line"
- ],
- "tests": [
- "assert(starRegex.flags.match(/g/).length == 1, 'message: Your regex starRegex
should use the global flag g
');",
- "assert(starRegex.flags.match(/i/).length == 1, 'message: Your regex starRegex
should use the case insensitive flag i
');",
- "assert(result.sort().join() == twinkleStar.match(/twinkle/gi).sort().join(), 'message: Your match should match both occurrences of the word \"Twinkle\"
');",
- "assert(result.length == 2, 'message: Your match result
should have two elements in it.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db5367417b2b2512b94",
- "title": "Match Anything with Wildcard Period",
- "description": [
- "Sometimes you won't (or don't need to) know the exact characters in your patterns. Thinking of all words that match, say, a misspelling would take a long time. Luckily, you can save time using the wildcard character: .
",
- "The wildcard character .
will match any one character. The wildcard is also called dot
and period
. You can use the wildcard character just like any other character in the regex. For example, if you wanted to match \"hug\"
, \"huh\"
, \"hut\"
, and \"hum\"
, you can use the regex /hu./
to match all four words.",
- "let humStr = \"I'll hum a song\";
",
- "
let hugStr = \"Bear hug\";
let huRegex = /hu./;
humStr.match(huRegex); // Returns [\"hum\"]
hugStr.match(huRegex); // Returns [\"hug\"]
",
- "Complete the regex unRegex
so that it matches the strings \"run\"
, \"sun\"
, \"fun\"
, \"pun\"
, \"nun\"
, and \"bun\"
. Your regex should use the wildcard character."
- ],
- "challengeSeed": [
- "let exampleStr = \"Let's have fun with regular expressions!\";",
- "let unRegex = /change/; // Change this line",
- "let result = unRegex.test(exampleStr);"
- ],
- "tests": [
- "assert(code.match(/\\.test\\(.*\\)/), 'message: You should use the .test()
method.');",
- "assert(/\\./.test(unRegex.source), 'message: You should use the wildcard character in your regex unRegex
');",
- "assert(unRegex.test(\"Let us go on a run.\"), 'message: Your regex unRegex
should match \"run\"
in \"Let us go on a run.\"
');",
- "assert(unRegex.test(\"The sun is out today.\"), 'message: Your regex unRegex
should match \"sun\"
in \"The sun is out today.\"
');",
- "assert(unRegex.test(\"Coding is a lot of fun.\"), 'message: Your regex unRegex
should match \"fun\"
in \"Coding is a lot of fun.\"
');",
- "assert(unRegex.test(\"Seven days without a pun makes one weak.\"), 'message: Your regex unRegex
should match \"pun\"
in \"Seven days without a pun makes one weak.\"
');",
- "assert(unRegex.test(\"One takes a vow to be a nun.\"), 'message: Your regex unRegex
should match \"nun\"
in \"One takes a vow to be a nun.\"
');",
- "assert(unRegex.test(\"She got fired from the hot dog stand for putting her hair in a bun.\"), 'message: Your regex unRegex
should match \"bun\"
in \"She got fired from the hot dog stand for putting her hair in a bun.\"
');",
- "assert(!unRegex.test(\"There is a bug in my code.\"), 'message: Your regex unRegex
should not match \"There is a bug in my code.\"
');",
- "assert(!unRegex.test(\"Can me if you can.\"), 'message: Your regex unRegex
should not match \"Catch me if you can.\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db5367417b2b2512b95",
- "title": "Match Single Character with Multiple Possibilities",
- "description": [
- "You learned how to match literal patterns (/literal/
) and wildcard character (/./
). Those are the extremes of regular expressions, where one finds exact matches and the other matches everything. There are options that are a balance between the two extremes.",
- "You can search for a literal pattern with some flexibility with character classes
. Character classes allow you to define a group of characters you wish to match by placing them inside square ([
and ]
) brackets.",
- "For example, you want to match \"bag\"
, \"big\"
, and \"bug\"
but not \"bog\"
. You can create the regex /b[aiu]g/
to do this. The [aiu]
is the character class that will only match the characters \"a\"
, \"i\"
, or \"u\"
.",
- "let bigStr = \"big\";
",
- "
let bagStr = \"bag\";
let bugStr = \"bug\";
let bogStr = \"bog\";
let bgRegex = /b[aiu]g/;
bigStr.match(bgRegex); // Returns [\"big\"]
bagStr.match(bgRegex); // Returns [\"bag\"]
bugStr.match(bgRegex); // Returns [\"bug\"]
bogStr.match(bgRegex); // Returns null
",
- "Use a character class with vowels (a
, e
, i
, o
, u
) in your regex vowelRegex
to find all the vowels in the string quoteSample
.",
- "Note
Be sure to match both upper- and lowercase vowels."
- ],
- "challengeSeed": [
- "let quoteSample = \"Beware of bugs in the above code; I have only proved it correct, not tried it.\";",
- "let vowelRegex = /change/; // Change this line",
- "let result = vowelRegex; // Change this line"
- ],
- "tests": [
- "assert(result.length == 25, 'message: You should find all 25 vowels.');",
- "assert(/\\[.*\\]/.test(vowelRegex.source), 'message: Your regex vowelRegex
should use a character class.');",
- "assert(vowelRegex.flags.match(/g/).length == 1, 'message: Your regex vowelRegex
should use the global flag.');",
- "assert(vowelRegex.flags.match(/i/).length == 1, 'message: Your regex vowelRegex
should use the case insensitive flag.');",
- "assert(!/[b-df-hj-np-tv-z]/gi.test(result.join()), 'message: Your regex should not match any consonants.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db5367417b2b2512b96",
- "title": "Match Letters of the Alphabet",
- "description": [
- "You saw how you can use character sets
to specify a group of characters to match, but that's a lot of typing when you need to match a large range of characters (for example, every letter in the alphabet). Fortunately, there is a built-in feature that makes this short and simple.",
- "Inside a character set
, you can define a range of characters to match using a hyphen
character: -
.",
- "For example, to match lowercase letters a
through e
you would use [a-e]
.",
- "let catStr = \"cat\";
",
- "
let batStr = \"bat\";
let matStr = \"mat\";
let bgRegex = /[a-e]at/;
catStr.match(bgRegex); // Returns [\"cat\"]
batStr.match(bgRegex); // Returns [\"bat\"]
matStr.match(bgRegex); // Returns null
",
- "Match all the letters in the string quoteSample
.",
- "Note
Be sure to match both upper- and lowercase vowels."
- ],
- "challengeSeed": [
- "let quoteSample = \"The quick brown fox jumps over the lazy dog.\";",
- "let alphabetRegex = /change/; // Change this line",
- "let result = alphabetRegex; // Change this line"
- ],
- "tests": [
- "assert(result.length == 35, 'message: Your regex alphabetRegex
should match 35 items.');",
- "assert(alphabetRegex.flags.match(/g/).length == 1, 'message: Your regex alphabetRegex
should use the global flag.');",
- "assert(alphabetRegex.flags.match(/i/).length == 1, 'message: Your regex alphabetRegex
should use the case insensitive flag.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db5367417b2b2512b97",
- "title": "Match Numbers and Letters of the Alphabet",
- "description": [
- "Using the hyphen (-
) to match a range of characters is not limited to letters. It also works to match a range of numbers.",
- "For example, /[0-5]/
matches any number between 0
and 5
, including the 0
and 5
.",
- "Also, it is possible to combine a range of letters and numbers in a single character set.",
- "let jennyStr = \"Jenny8675309\";
",
- "
let myRegex = /[a-z0-9]/ig;
// matches all letters and numbers in jennyStr
jennyStr.match(myRegex);
",
- "Create a single regex that matches a range of letters between h
and s
, and a range of numbers between 2
and 6
. Remember to include the appropriate flags in the regex."
- ],
- "challengeSeed": [
- "let quoteSample = \"Blueberry 3.141592653s are delicious.\";",
- "let myRegex = /change/; // Change this line",
- "let result = myRegex; // Change this line"
- ],
- "tests": [
- "assert(result.length == 17, 'message: Your regex myRegex
should match 17 items.');",
- "assert(myRegex.flags.match(/g/).length == 1, 'message: Your regex myRegex
should use the global flag.');",
- "assert(myRegex.flags.match(/i/).length == 1, 'message: Your regex myRegex
should use the case insensitive flag.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db6367417b2b2512b98",
- "title": "Match Single Characters Not Specified",
- "description": [
- "So far, you have created a set of characters that you want to match, but you could also create a set of characters that you do not want to match. These types of character sets are called negated character sets
.",
- "To create a negated character set
, you place a caret
character (^
) after the opening bracket and before the characters you do not want to match.",
- "For example, /[^aeiou]/gi
matches all characters that are not a vowel. Note that characters like .
, !
, [
, @
, /
and white space are matched - the negated vowel character set only excludes the vowel characters.",
- "
",
- "Create a single regex that matches all characters that are not a number or a vowel. Remember to include the appropriate flags in the regex."
- ],
- "challengeSeed": [
- "let quoteSample = \"3 blind mice.\";",
- "let myRegex = /change/; // Change this line",
- "let result = myRegex; // Change this line"
- ],
- "tests": [
- "assert(result.length == 9, 'message: Your regex myRegex
should match 9 items.');",
- "assert(myRegex.flags.match(/g/).length == 1, 'message: Your regex myRegex
should use the global flag.');",
- "assert(myRegex.flags.match(/i/).length == 1, 'message: Your regex myRegex
should use the case insensitive flag.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db6367417b2b2512b99",
- "title": "Match Characters that Occur One or More Times",
- "description": [
- "Sometimes, you need to match a character (or group of characters) that appears one or more times in a row. This means it occurs at least once, and may be repeated.",
- "You can use the +
character to check if that is the case. Remember, the character or pattern has to be present consecutively. That is, the character has to repeat one after the other.",
- "For example, /a+/g
would find one match in \"abc\"
and return [\"a\"]
. Because of the +
, it would also find a single match in \"aabc\"
and return [\"aa\"]
.",
- "If it were instead checking the string \"abab\"
, it would find two matches and return [\"a\", \"a\"]
because the a
characters are not in a row - there is a b
between them. Finally, since there is no \"a\"
in the string \"bcd\"
, it wouldn't find a match.",
- "
",
- "You want to find matches when the letter s
occurs one or more times in \"Mississippi\"
. Write a regex that uses the +
sign."
- ],
- "challengeSeed": [
- "let difficultSpelling = \"Mississippi\";",
- "let myRegex = /change/; // Change this line",
- "let result = difficultSpelling.match(myRegex);"
- ],
- "tests": [
- "assert(/\\+/.test(myRegex.source), 'message: Your regex myRegex
should use the +
sign to match one or more s
characters.');",
- "assert(result.length == 2, 'message: Your regex myRegex
should match 2 items.');",
- "assert(result[0] == 'ss' && result[1] == 'ss', 'message: The result
variable should be an array with two matches of \"ss\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db6367417b2b2512b9a",
- "title": "Match Characters that Occur Zero or More Times",
- "description": [
- "The last challenge used the plus +
sign to look for characters that occur one or more times. There's also an option that matches characters that occur zero or more times.",
- "The character to do this is the asterisk
or star
: *
.",
- "let soccerWord = \"gooooooooal!\";
",
- "
let gPhrase = \"gut feeling\";
let oPhrase = \"over the moon\";
let goRegex = /go*/;
soccerWord.match(goRegex); // Returns [\"goooooooo\"]
gPhrase.match(goRegex); // Returns [\"g\"]
oPhrase.match(goRegex); // Returns null
",
- "Create a regex chewieRegex
that uses the *
character to match all the upper and lower\"a\"
characters in chewieQuote
. Your regex does not need flags, and it should not match any of the other quotes."
- ],
- "challengeSeed": [
- "let chewieQuote = \"Aaaaaaaaaaaaaaaarrrgh!\";",
- "let chewieRegex = /change/; // Change this line",
- "let result = chewieQuote.match(chewieRegex);"
- ],
- "tests": [
- "assert(/\\*/.test(chewieRegex.source), 'message: Your regex chewieRegex
should use the *
character to match zero or more a
characters.');",
- "assert(result[0].length === 16, 'message: Your regex chewieRegex
should match 16 characters.');",
- "assert(result[0] === 'Aaaaaaaaaaaaaaaa', 'message: Your regex should match \"Aaaaaaaaaaaaaaaa\"
.');",
- "assert(!\"He made a fair move. Screaming about it can\\'t help you.\".match(chewieRegex), 'message: Your regex should not match any characters in \"He made a fair move. Screaming about it can't help you.\"
');",
- "assert(!\"Let him have it. It\\'s not wise to upset a Wookiee.\".match(chewieRegex), 'message: Your regex should not match any characters in \"Let him have it. It's not wise to upset a Wookiee.\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db6367417b2b2512b9b",
- "title": "Find Characters with Lazy Matching",
- "description": [
- "In regular expressions, a greedy
match finds the longest possible part of a string that fits the regex pattern and returns it as a match. The alternative is called a lazy
match, which finds the smallest possible part of the string that satisfies the regex pattern.",
- "You can apply the regex /t[a-z]*i/
to the string \"titanic\"
. This regex is basically a pattern that starts with t
, ends with i
, and has some letters in between.",
- "Regular expressions are by default greedy
, so the match would return [\"titani\"]
. It finds the largest sub-string possible to fit the pattern.",
- "However, you can use the ?
character to change it to lazy
matching. \"titanic\"
matched against the adjusted regex of /t[a-z]*?i/
returns [\"ti\"]
.",
- "
",
- "Fix the regex /<.*>/
to return the HTML tag <h1>
and not the text \"<h1>Winter is coming</h1>\"
. Remember the wildcard .
in a regular expression matches any character."
- ],
- "challengeSeed": [
- "let text = \"Winter is coming
\";",
- "let myRegex = /<.*>/; // Change this line",
- "let result = text.match(myRegex);"
- ],
- "tests": [
- "assert(result[0] == '', 'message: The
result
variable should be an array with <h1>
in it');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db7367417b2b2512b9c",
- "title": "Find One or More Criminals in a Hunt",
- "description": [
- "Time to pause and test your new regex writing skills. A group of criminals escaped from jail and ran away, but you don't know how many. However, you do know that they stay close together when they are around other people. You are responsible for finding all of the criminals at once.",
- "Here's an example to review how to do this:",
- "The regex /z+/
matches the letter z
when it appears one or more times in a row. It would find matches in all of the following strings:",
- "\"z\"
",
- "But it does not find matches in the following strings since there are no letter
\"zzzzzz\"
\"ABCzzzz\"
\"zzzzABC\"
\"abczzzzzzzzzzzzzzzzzzzzzabc\"z
characters:",
- "\"\"
",
- "
\"ABC\"
\"abcabc\"
",
- "Write a greedy
regex that finds one or more criminals within a group of other people. A criminal is represented by the capital letter C
."
- ],
- "challengeSeed": [
- "// example crowd gathering",
- "let crowd = 'P1P2P3P4P5P6CCCP7P8P9';",
- "",
- "let reCriminals = /./; // Change this line",
- "",
- "let matchedCriminals = crowd.match(reCriminals);",
- "console.log(matchedCriminals);"
- ],
- "tests": [
- "assert('C'.match(reCriminals) && 'C'.match(reCriminals)[0] == 'C', 'message: Your regex should match one criminal (\"C
\") in \"C\"
');",
- "assert('CC'.match(reCriminals) && 'CC'.match(reCriminals)[0] == 'CC', 'message: Your regex should match two criminals (\"CC
\") in \"CC\"
');",
- "assert('P1P5P4CCCP2P6P3'.match(reCriminals) && 'P1P5P4CCCP2P6P3'.match(reCriminals)[0] == 'CCC', 'message: Your regex should match three criminals (\"CCC
\") in \"P1P5P4CCCP2P6P3\"
');",
- "assert('P6P2P7P4P5CCCCCP3P1'.match(reCriminals) && 'P6P2P7P4P5CCCCCP3P1'.match(reCriminals)[0] == 'CCCCC', 'message: Your regex should match five criminals (\"CCCCC
\") in \"P6P2P7P4P5CCCCCP3P1\"
');",
- "assert(!reCriminals.test(''), 'message: Your regex should not match any criminals in \"\"
');",
- "assert(!reCriminals.test('P1P2P3'), 'message: Your regex should not match any criminals in \"P1P2P3\"
');",
- "assert('P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3'.match(reCriminals) && 'P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3'.match(reCriminals)[0] == \"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\", 'message: Your regex should match fifty criminals (\"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
\") in \"P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3\"
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db7367417b2b2512b9d",
- "title": "Match Beginning String Patterns",
- "description": [
- "Prior challenges showed that regular expressions can be used to look for a number of matches. They are also used to search for patterns in specific positions in strings.",
- "In an earlier challenge, you used the caret
character (^
) inside a character set
to create a negated character set
in the form [^thingsThatWillNotBeMatched]
. Outside of a character set
, the caret
is used to search for patterns at the beginning of strings.",
- "let firstString = \"Ricky is first and can be found.\";
",
- "
let firstRegex = /^Ricky/;
firstRegex.test(firstString);
// Returns true
let notFirst = \"You can't find Ricky now.\";
firstRegex.test(notFirst);
// Returns false
",
- "Use the caret
character in a regex to find \"Cal\"
only in the beginning of the string rickyAndCal
."
- ],
- "challengeSeed": [
- "let rickyAndCal = \"Cal and Ricky both like racing.\";",
- "let calRegex = /change/; // Change this line",
- "let result = calRegex.test(rickyAndCal);"
- ],
- "tests": [
- "assert(calRegex.source == \"^Cal\", 'message: Your regex should search for \"Cal\"
with a capital letter.');",
- "assert(calRegex.flags == \"\", 'message: Your regex should not use any flags.');",
- "assert(calRegex.test(\"Cal and Ricky both like racing.\"), 'message: Your regex should match \"Cal\"
at the beginning of the string.');",
- "assert(!calRegex.test(\"Ricky and Cal both like racing.\"), 'message: Your regex should not match \"Cal\"
in the middle of a string.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db7367417b2b2512b9e",
- "title": "Match Ending String Patterns",
- "description": [
- "In the last challenge, you learned to use the caret
character to search for patterns at the beginning of strings. There is also a way to search for patterns at the end of strings.",
- "You can search the end of strings using the dollar sign
character $
at the end of the regex.",
- "let theEnding = \"This is a never ending story\";
",
- "
let storyRegex = /story$/;
storyRegex.test(theEnding);
// Returns true
let noEnding = \"Sometimes a story will have to end\";
storyRegex.test(noEnding);
// Returns false
",
- "Use the anchor character ($
) to match the string \"caboose\"
at the end of the string caboose
."
- ],
- "challengeSeed": [
- "let caboose = \"The last car on a train is the caboose\";",
- "let lastRegex = /change/; // Change this line",
- "let result = lastRegex.test(caboose);"
- ],
- "tests": [
- "assert(lastRegex.source == \"caboose$\", 'message: You should search for \"caboose\"
with the dollar sign $
anchor in your regex.');",
- "assert(lastRegex.flags == \"\", 'message: Your regex should not use any flags.');",
- "assert(lastRegex.test(\"The last car on a train is the caboose\"), 'message: You should match \"caboose\"
at the end of the string \"The last car on a train is the caboose\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db7367417b2b2512b9f",
- "title": "Match All Letters and Numbers",
- "description": [
- "Using character classes, you were able to search for all letters of the alphabet with [a-z]
. This kind of character class is common enough that there is a shortcut for it, although it includes a few extra characters as well.",
- "The closest character class in JavaScript to match the alphabet is \\w
. This shortcut is equal to [A-Za-z0-9_]
. This character class matches upper and lowercase letters plus numbers. Note, this character class also includes the underscore character (_
).",
- "let longHand = /[A-Za-z0-9_]+/;
",
- "These shortcut character classes are also known as
let shortHand = /\\w+/;
let numbers = \"42\";
let varNames = \"important_var\";
longHand.test(numbers); // Returns true
shortHand.test(numbers); // Returns true
longHand.test(varNames); // Returns true
shortHand.test(varNames); // Returns trueshorthand character classes
.",
- "
",
- "Use the shorthand character class \\w
to count the number of alphanumeric characters in various quotes and strings."
- ],
- "challengeSeed": [
- "let quoteSample = \"The five boxing wizards jump quickly.\";",
- "let alphabetRegexV2 = /change/; // Change this line",
- "let result = quoteSample.match(alphabetRegexV2).length;"
- ],
- "tests": [
- "assert(alphabetRegexV2.global, 'message: Your regex should use the global flag.');",
- "assert(\"The five boxing wizards jump quickly.\".match(alphabetRegexV2).length === 31, 'message: Your regex should find 31 alphanumeric characters in \"The five boxing wizards jump quickly.\"
');",
- "assert(\"Pack my box with five dozen liquor jugs.\".match(alphabetRegexV2).length === 32, 'message: Your regex should find 32 alphanumeric characters in \"Pack my box with five dozen liquor jugs.\"
');",
- "assert(\"How vexingly quick daft zebras jump!\".match(alphabetRegexV2).length === 30, 'message: Your regex should find 30 alphanumeric characters in \"How vexingly quick daft zebras jump!\"
');",
- "assert(\"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\".match(alphabetRegexV2).length === 36, 'message: Your regex should find 36 alphanumeric characters in \"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db8367417b2b2512ba0",
- "title": "Match Everything But Letters and Numbers",
- "description": [
- "You've learned that you can use a shortcut to match alphanumerics [A-Za-z0-9_]
using \\w
. A natural pattern you might want to search for is the opposite of alphanumerics.",
- "You can search for the opposite of the \\w
with \\W
. Note, the opposite pattern uses a capital letter. This shortcut is the same as [^A-Za-z0-9_]
.",
- "let shortHand = /\\W/;
",
- "
let numbers = \"42%\";
let sentence = \"Coding!\";
numbers.match(shortHand); // Returns [\"%\"]
sentence.match(shortHand); // Returns [\"!\"]
",
- "Use the shorthand character class \\W
to count the number of non-alphanumeric characters in various quotes and strings."
- ],
- "challengeSeed": [
- "let quoteSample = \"The five boxing wizards jump quickly.\";",
- "let nonAlphabetRegex = /change/; // Change this line",
- "let result = quoteSample.match(nonAlphabetRegex).length;"
- ],
- "tests": [
- "assert(nonAlphabetRegex.global, 'message: Your regex should use the global flag.');",
- "assert(\"The five boxing wizards jump quickly.\".match(nonAlphabetRegex).length == 6, 'message: Your regex should find 6 non-alphanumeric characters in \"The five boxing wizards jump quickly.\"
.');",
- "assert(\"Pack my box with five dozen liquor jugs.\".match(nonAlphabetRegex).length == 8, 'message: Your regex should find 8 non-alphanumeric characters in \"Pack my box with five dozen liquor jugs.\"
');",
- "assert(\"How vexingly quick daft zebras jump!\".match(nonAlphabetRegex).length == 6, 'message: Your regex should find 6 non-alphanumeric characters in \"How vexingly quick daft zebras jump!\"
');",
- "assert(\"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\".match(nonAlphabetRegex).length == 12, 'message: Your regex should find 12 non-alphanumeric characters in \"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "5d712346c441eddfaeb5bdef",
- "title": "Match All Numbers",
- "description": [
- "You've learned shortcuts for common string patterns like alphanumerics. Another common pattern is looking for just digits or numbers.",
- "The shortcut to look for digit characters is \\d
, with a lowercase d
. This is equal to the character class [0-9]
, which looks for a single character of any number between zero and nine.",
- "
",
- "Use the shorthand character class \\d
to count how many digits are in movie titles. Written out numbers (\"six\" instead of 6) do not count."
- ],
- "challengeSeed": [
- "let numString = \"Your sandwich will be $5.00\";",
- "let numRegex = /change/; // Change this line",
- "let result = numString.match(numRegex).length;"
- ],
- "tests": [
- "assert(/\\\\d/.test(numRegex.source), 'message: Your regex should use the shortcut character to match digit characters');",
- "assert(numRegex.global, 'message: Your regex should use the global flag.');",
- "assert(\"9\".match(numRegex).length == 1, 'message: Your regex should find 1 digit in \"9\"
.');",
- "assert(\"Catch 22\".match(numRegex).length == 2, 'message: Your regex should find 2 digits in \"Catch 22\"
.');",
- "assert(\"101 Dalmatians\".match(numRegex).length == 3, 'message: Your regex should find 3 digits in \"101 Dalmatians\"
.');",
- "assert(\"One, Two, Three\".match(numRegex) == null, 'message: Your regex should find no digits in \"One, Two, Three\"
.');",
- "assert(\"21 Jump Street\".match(numRegex).length == 2, 'message: Your regex should find 2 digits in \"21 Jump Street\"
.');",
- "assert(\"2001: A Space Odyssey\".match(numRegex).length == 4, 'message: Your regex should find 4 digits in \"2001: A Space Odyssey\"
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db8367417b2b2512ba1",
- "title": "Match All Non-Numbers",
- "description": [
- "The last challenge showed how to search for digits using the shortcut \\d
with a lowercase d
. You can also search for non-digits using a similar shortcut that uses an uppercase D
instead.",
- "The shortcut to look for non-digit characters is \\D
. This is equal to the character class [^0-9]
, which looks for a single character that is not a number between zero and nine.",
- "
",
- "Use the shorthand character class for non-digits \\D
to count how many non-digits are in movie titles."
- ],
- "challengeSeed": [
- "let numString = \"Your sandwich will be $5.00\";",
- "let noNumRegex = /change/; // Change this line",
- "let result = numString.match(noNumRegex).length;"
- ],
- "tests": [
- "assert(/\\\\D/.test(noNumRegex.source), 'message: Your regex should use the shortcut character to match non-digit characters');",
- "assert(noNumRegex.global, 'message: Your regex should use the global flag.');",
- "assert(\"9\".match(noNumRegex) == null, 'message: Your regex should find no non-digits in \"9\"
.');",
- "assert(\"Catch 22\".match(noNumRegex).length == 6, 'message: Your regex should find 6 non-digits in \"Catch 22\"
.');",
- "assert(\"101 Dalmatians\".match(noNumRegex).length == 11, 'message: Your regex should find 11 non-digits in \"101 Dalmatians\"
.');",
- "assert(\"One, Two, Three\".match(noNumRegex).length == 15, 'message: Your regex should find 15 non-digits in \"One, Two, Three\"
.');",
- "assert(\"21 Jump Street\".match(noNumRegex).length == 12, 'message: Your regex should find 12 non-digits in \"21 Jump Street\"
.');",
- "assert(\"2001: A Space Odyssey\".match(noNumRegex).length == 17, 'message: Your regex should find 17 non-digits in \"2001: A Space Odyssey\"
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db8367417b2b2512ba2",
- "title": "Restrict Possible Usernames",
- "description": [
- "Usernames are used everywhere on the internet. They are what give users a unique identity on their favorite sites.",
- "You need to check all the usernames in a database. Here are some simple rules that users have to follow when creating their username.",
- "1) The only numbers in the username have to be at the end. There can be zero or more of them at the end.",
- "2) Username letters can be lowercase and uppercase.",
- "3) Usernames have to be at least two characters long. A two-letter username can only use alphabet letter characters.",
- "
",
- "Change the regex userCheck
to fit the constraints listed above."
- ],
- "challengeSeed": [
- "let username = \"JackOfAllTrades\";",
- "let userCheck = /change/; // Change this line",
- "let result = userCheck.test(username);"
- ],
- "tests": [
- "assert(userCheck.test(\"JACK\"), 'message: Your regex should match JACK
');",
- "assert(!userCheck.test(\"J\"), 'message: Your regex should not match J
');",
- "assert(userCheck.test(\"Oceans11\"), 'message: Your regex should match Oceans11
');",
- "assert(userCheck.test(\"RegexGuru\"), 'message: Your regex should match RegexGuru
');",
- "assert(!userCheck.test(\"007\"), 'message: Your regex should not match 007
');",
- "assert(!userCheck.test(\"9\"), 'message: Your regex should not match 9
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db8367417b2b2512ba3",
- "title": "Match Whitespace",
- "description": [
- "The challenges so far have covered matching letters of the alphabet and numbers. You can also match the whitespace or spaces between letters.",
- "You can search for whitespace using \\s
, which is a lowercase s
. This pattern not only matches whitespace, but also carriage return, tab, form feed, and new line characters. You can think of it as similar to the character class [ \\r\\t\\f\\n\\v]
.",
- "let whiteSpace = \"Whitespace. Whitespace everywhere!\"
",
- "
let spaceRegex = /\\s/g;
whiteSpace.match(spaceRegex);
// Returns [\" \", \" \"]
",
- "Change the regex countWhiteSpace
to look for multiple whitespace characters in a string."
- ],
- "challengeSeed": [
- "let sample = \"Whitespace is important in separating words\";",
- "let countWhiteSpace = /change/; // Change this line",
- "let result = sample.match(countWhiteSpace);"
- ],
- "tests": [
- "assert(countWhiteSpace.global, 'message: Your regex should use the global flag.');",
- "assert(\"Men are from Mars and women are from Venus.\".match(countWhiteSpace).length == 8, 'message: Your regex should find eight spaces in \"Men are from Mars and women are from Venus.\"
');",
- "assert(\"Space: the final frontier.\".match(countWhiteSpace).length == 3, 'message: Your regex should find three spaces in \"Space: the final frontier.\"
');",
- "assert(\"MindYourPersonalSpace\".match(countWhiteSpace) == null, 'message: Your regex should find no spaces in \"MindYourPersonalSpace\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db9367417b2b2512ba4",
- "title": "Match Non-Whitespace Characters",
- "description": [
- "You learned about searching for whitespace using \\s
, with a lowercase s
. You can also search for everything except whitespace.",
- "Search for non-whitespace using \\S
, which is an uppercase s
. This pattern will not match whitespace, carriage return, tab, form feed, and new line characters. You can think of it being similar to the character class [^ \\r\\t\\f\\n\\v]
.",
- "let whiteSpace = \"Whitespace. Whitespace everywhere!\"
",
- "
let nonSpaceRegex = /\\S/g;
whiteSpace.match(nonSpaceRegex).length; // Returns 32
",
- "Change the regex countNonWhiteSpace
to look for multiple non-whitespace characters in a string."
- ],
- "challengeSeed": [
- "let sample = \"Whitespace is important in separating words\";",
- "let countNonWhiteSpace = /change/; // Change this line",
- "let result = sample.match(countNonWhiteSpace);"
- ],
- "tests": [
- "assert(countNonWhiteSpace.global, 'message: Your regex should use the global flag.');",
- "assert(\"Men are from Mars and women are from Venus.\".match(countNonWhiteSpace).length == 35, 'message: Your regex should find 35 non-spaces in \"Men are from Mars and women are from Venus.\"
');",
- "assert(\"Space: the final frontier.\".match(countNonWhiteSpace).length == 23, 'message: Your regex should find 23 non-spaces in \"Space: the final frontier.\"
');",
- "assert(\"MindYourPersonalSpace\".match(countNonWhiteSpace).length == 21, 'message: Your regex should find 21 non-spaces in \"MindYourPersonalSpace\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db9367417b2b2512ba5",
- "title": "Specify Upper and Lower Number of Matches",
- "description": [
- "Recall that you use the plus sign +
to look for one or more characters and the asterisk *
to look for zero or more characters. These are convenient but sometimes you want to match a certain range of patterns.",
- "You can specify the lower and upper number of patterns with quantity specifiers
. Quantity specifiers are used with curly brackets ({
and }
). You put two numbers between the curly brackets - for the lower and upper number of patterns.",
- "For example, to match only the letter a
appearing between 3
and 5
times in the string \"ah\"
, your regex would be /a{3,5}h/
.",
- "let A4 = \"aaaah\";
",
- "
let A2 = \"aah\";
let multipleA = /a{3,5}h/;
multipleA.test(A4); // Returns true
multipleA.test(A2); // Returns false
",
- "Change the regex ohRegex
to match only 3
to 6
letter h
's in the word \"Oh no\"
."
- ],
- "challengeSeed": [
- "let ohStr = \"Ohhh no\";",
- "let ohRegex = /change/; // Change this line",
- "let result = ohRegex.test(ohStr);"
- ],
- "tests": [
- "assert(ohRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');",
- "assert(!ohRegex.test(\"Ohh no\"), 'message: Your regex should not match \"Ohh no\"
');",
- "assert(ohRegex.test(\"Ohhh no\"), 'message: Your regex should match \"Ohhh no\"
');",
- "assert(ohRegex.test(\"Ohhhh no\"), 'message: Your regex should match \"Ohhhh no\"
');",
- "assert(ohRegex.test(\"Ohhhhh no\"), 'message: Your regex should match \"Ohhhhh no\"
');",
- "assert(ohRegex.test(\"Ohhhhhh no\"), 'message: Your regex should match \"Ohhhhhh no\"
');",
- "assert(!ohRegex.test(\"Ohhhhhhh no\"), 'message: Your regex should not match \"Ohhhhhhh no\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db9367417b2b2512ba6",
- "title": "Specify Only the Lower Number of Matches",
- "description": [
- "You can specify the lower and upper number of patterns with quantity specifiers
using curly brackets. Sometimes you only want to specify the lower number of patterns with no upper limit.",
- "To only specify the lower number of patterns, keep the first number followed by a comma.",
- "For example, to match only the string \"hah\"
with the letter a
appearing at least 3
times, your regex would be /ha{3,}h/
.",
- "let A4 = \"haaaah\";
",
- "
let A2 = \"haah\";
let A100 = \"h\" + \"a\".repeat(100) + \"h\";
let multipleA = /ha{3,}h/;
multipleA.test(A4); // Returns true
multipleA.test(A2); // Returns false
multipleA.test(A100); // Returns true
",
- "Change the regex haRegex
to match the word \"Hazzah\"
only when it has four or more letter z
's."
- ],
- "challengeSeed": [
- "let haStr = \"Hazzzzah\";",
- "let haRegex = /change/; // Change this line",
- "let result = haRegex.test(haStr);"
- ],
- "tests": [
- "assert(haRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');",
- "assert(!haRegex.test(\"Hazzah\"), 'message: Your regex should not match \"Hazzah\"
');",
- "assert(!haRegex.test(\"Hazzzah\"), 'message: Your regex should not match \"Hazzzah\"
');",
- "assert(haRegex.test(\"Hazzzzah\"), 'message: Your regex should match \"Hazzzzah\"
');",
- "assert(haRegex.test(\"Hazzzzzah\"), 'message: Your regex should match \"Hazzzzzah\"
');",
- "assert(haRegex.test(\"Hazzzzzzah\"), 'message: Your regex should match \"Hazzzzzzah\"
');",
- "assert(haRegex.test(\"Ha\" + \"z\".repeat(30) + \"ah\"), 'message: Your regex should match \"Hazzah\"
with 30 z
\\'s in it.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7db9367417b2b2512ba7",
- "title": "Specify Exact Number of Matches",
- "description": [
- "You can specify the lower and upper number of patterns with quantity specifiers
using curly brackets. Sometimes you only want a specific number of matches.",
- "To specify a certain number of patterns, just have that one number between the curly brackets.",
- "For example, to match only the word \"hah\"
with the letter a
3
times, your regex would be /ha{3}h/
.",
- "let A4 = \"haaaah\";
",
- "
let A3 = \"haaah\";
let A100 = \"h\" + \"a\".repeat(100) + \"h\";
let multipleHA = /a{3}h/;
multipleHA.test(A4); // Returns false
multipleHA.test(A3); // Returns true
multipleHA.test(A100); // Returns false
",
- "Change the regex timRegex
to match the word \"Timber\"
only when it has four letter m
's."
- ],
- "challengeSeed": [
- "let timStr = \"Timmmmber\";",
- "let timRegex = /change/; // Change this line",
- "let result = timRegex.test(timStr);"
- ],
- "tests": [
- "assert(timRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');",
- "assert(!timRegex.test(\"Timber\"), 'message: Your regex should not match \"Timber\"
');",
- "assert(!timRegex.test(\"Timmber\"), 'message: Your regex should not match \"Timmber\"
');",
- "assert(!timRegex.test(\"Timmmber\"), 'message: Your regex should not match \"Timmmber\"
');",
- "assert(timRegex.test(\"Timmmmber\"), 'message: Your regex should match \"Timmmmber\"
');",
- "assert(!timRegex.test(\"Ti\" + \"m\".repeat(30) + \"ber\"), 'message: Your regex should not match \"Timber\"
with 30 m
\\'s in it.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dba367417b2b2512ba8",
- "title": "Check for All or None",
- "description": [
- "Sometimes the patterns you want to search for may have parts of it that may or may not exist. However, it may be important to check for them nonetheless.",
- "You can specify the possible existence of an element with a question mark, ?
. This checks for zero or one of the preceding element. You can think of this symbol as saying the previous element is optional.",
- "For example, there are slight differences in American and British English and you can use the question mark to match both spellings.",
- "let american = \"color\";
",
- "
let british = \"colour\";
let rainbowRegex= /colou?r/;
rainbowRegex.test(american); // Returns true
rainbowRegex.test(british); // Returns true
",
- "Change the regex favRegex
to match both the American English (favorite) and the British English (favourite) version of the word."
- ],
- "challengeSeed": [
- "let favWord = \"favorite\";",
- "let favRegex = /change/; // Change this line",
- "let result = favRegex.test(favWord);"
- ],
- "tests": [
- "assert(favRegex.source.match(/\\?/).length > 0, 'message: Your regex should use the optional symbol, ?
.');",
- "assert(favRegex.test(\"favorite\"), 'message: Your regex should match \"favorite\"
');",
- "assert(favRegex.test(\"favourite\"), 'message: Your regex should match \"favourite\"
');",
- "assert(!favRegex.test(\"fav\"), 'message: Your regex should not match \"fav\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dba367417b2b2512ba9",
- "title": "Positive and Negative Lookahead",
- "description": [
- "Lookaheads
are patterns that tell JavaScript to look-ahead in your string to check for patterns further along. This can be useful when you want to search for multiple patterns over the same string.",
- "There are two kinds of lookaheads
: positive lookahead
and negative lookahead
.",
- "A positive lookahead
will look to make sure the element in the search pattern is there, but won't actually match it. A positive lookahead is used as (?=...)
where the ...
is the required part that is not matched.",
- "On the other hand, a negative lookahead
will look to make sure the element in the search pattern is not there. A negative lookahead is used as (?!...)
where the ...
is the pattern that you do not want to be there. The rest of the pattern is returned if the negative lookahead part is not present.",
- "Lookaheads are a bit confusing but some examples will help.",
- "let quit = \"qu\";
",
- "A more practical use of
let noquit = \"qt\";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex); // Returns [\"q\"]
noquit.match(qRegex); // Returns [\"q\"]lookaheads
is to check two or more patterns in one string. Here is a (naively) simple password checker that looks for between 3 and 6 characters and at least one number:",
- "let password = \"abc123\";
",
- "
let checkPass = /(?=\\w{3,6})(?=\\D*\\d)/;
checkPass.test(password); // Returns true
",
- "Use lookaheads
in the pwRegex
to match passwords that are greater than 5 characters long and have two consecutive digits."
- ],
- "challengeSeed": [
- "let sampleWord = \"astronaut\";",
- "let pwRegex = /change/; // Change this line",
- "let result = pwRegex.test(sampleWord);"
- ],
- "tests": [
- "assert(pwRegex.source.match(/\\(\\?=.*?\\)\\(\\?=.*?\\)/) !== null, 'message: Your regex should use two positive lookaheads
.');",
- "assert(!pwRegex.test(\"astronaut\"), 'message: Your regex should not match \"astronaut\"
');",
- "assert(!pwRegex.test(\"airplanes\"), 'message: Your regex should not match \"airplanes\"
');",
- "assert(pwRegex.test(\"bana12\"), 'message: Your regex should match \"bana12\"
');",
- "assert(pwRegex.test(\"abc123\"), 'message: Your regex should match \"abc123\"
');",
- "assert(!pwRegex.test(\"123\"), 'message: Your regex should not match \"123\"
');",
- "assert(!pwRegex.test(\"1234\"), 'message: Your regex should not match \"1234\"
');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dbb367417b2b2512baa",
- "title": "Reuse Patterns Using Capture Groups",
- "description": [
- "Some patterns you search for will occur multiple times in a string. It is wasteful to manually repeat that regex. There is a better way to specify when you have multiple repeat substrings in your string.",
- "You can search for repeat substrings using capture groups
. Parentheses, (
and )
, are used to find repeat substrings. You put the regex of the pattern that will repeat in between the parentheses.",
- "To specify where that repeat string will appear, you use a backslash (\\
) and then a number. This number starts at 1 and increases with each additional capture group you use. An example would be \\1
to match the first group.",
- "The example below matches any word that occurs twice separated by a space:",
- "let repeatStr = \"regex regex\";
",
- "Using the
let repeatRegex = /(\\w+)\\s\\1/;
repeatRegex.test(repeatStr); // Returns true
repeatStr.match(repeatRegex); // Returns [\"regex regex\", \"regex\"].match()
method on a string will return an array with the string it matches, along with its capture group.",
- "
",
- "Use capture groups
in reRegex
to match numbers that are repeated only three times in a string, each separated by a space."
- ],
- "challengeSeed": [
- "let repeatNum = \"42 42 42\";",
- "let reRegex = /change/; // Change this line",
- "let result = reRegex.test(repeatNum);"
- ],
- "tests": [
- "assert(reRegex.source.match(/\\\\d/), 'message: Your regex should use the shorthand character class for digits.');",
- "assert(reRegex.source.match(/\\\\\\d/g).length === 2, 'message: Your regex should reuse the capture group twice.');",
- "assert(reRegex.source.match(/\\\\s/g).length === 2, 'message: Your regex should have two spaces separating the three numbers.');",
- "assert(reRegex.test(\"42 42 42\"), 'message: Your regex should match \"42 42 42\"
.');",
- "assert(reRegex.test(\"100 100 100\"), 'message: Your regex should match \"100 100 100\"
.');",
- "assert.equal((\"42 42 42 42\").match(reRegex.source), null, 'message: Your regex should not match \"42 42 42 42\"
.');",
- "assert.equal((\"42 42\").match(reRegex.source), null, 'message: Your regex should not match \"42 42\"
.');",
- "assert(!reRegex.test(\"101 102 103\"), 'message: Your regex should not match \"101 102 103\"
.');",
- "assert(!reRegex.test(\"1 2 3\"), 'message: Your regex should not match \"1 2 3\"
.');",
- "assert(reRegex.test(\"10 10 10\"), 'message: Your regex should match \"10 10 10\"
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dbb367417b2b2512bab",
- "title": "Use Capture Groups to Search and Replace",
- "description": [
- "Searching is useful. However, you can make searching even more powerful when it also changes (or replaces) the text you match.",
- "You can search and replace text in a string using .replace()
on a string. The inputs for .replace()
is first the regex pattern you want to search for. The second parameter is the string to replace the match or a function to do something.",
- "let wrongText = \"The sky is silver.\";
",
- "You can also access capture groups in the replacement string with dollar signs (
let silverRegex = /silver/;
wrongText.replace(silverRegex, \"blue\");
// Returns \"The sky is blue.\"$
).",
- "\"Code Camp\".replace(/(\\w+)\\s(\\w+)/, '$2 $1');
",
- "
// Returns \"Camp Code\"
",
- "Write a regex so that it will search for the string \"good\"
. Then update the replaceText
variable to replace \"good\"
with \"okey-dokey\"
."
- ],
- "challengeSeed": [
- "let huhText = \"This sandwich is good.\";",
- "let fixRegex = /change/; // Change this line",
- "let replaceText = \"\"; // Change this line",
- "let result = huhText.replace(fixRegex, replaceText);"
- ],
- "tests": [
- "assert(code.match(/\\.replace\\(.*\\)/), 'message: You should use .replace()
to search and replace.');",
- "assert(result == \"This sandwich is okey-dokey.\" && replaceText === \"okey-dokey\", 'message: Your regex should change \"This sandwich is good.\"
to \"This sandwich is okey-dokey.\"
');",
- "assert(code.match(/result\\s*=\\s*huhText\\.replace\\(.*?\\)/), 'message: You should not change the last line.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- },
- {
- "id": "587d7dbb367417b2b2512bac",
- "title": "Remove Whitespace from Start and End",
- "description": [
- "Sometimes whitespace characters around strings are not wanted but are there. Typical processing of strings is to remove the whitespace at the start and end of it.",
- "
",
- "Write a regex and use the appropriate string methods to remove whitespace at the beginning and end of strings.",
- "Note
The .trim()
method would work here, but you'll need to complete this challenge using regular expressions."
- ],
- "challengeSeed": [
- "let hello = \" Hello, World! \";",
- "let wsRegex = /change/; // Change this line",
- "let result = hello; // Change this line"
- ],
- "tests": [
- "assert(result == \"Hello, World!\", 'message: result
should equal to \"Hello, World!\"
');",
- "assert(!code.match(/\\.trim\\(.*?\\)/), 'message: You should not use the .trim()
method.');",
- "assert(!code.match(/result\\s*=\\s*\".*?\"/), 'message: The result
variable should not be set equal to a string.');"
- ],
- "solutions": [],
- "hints": [
- "You can use .replace() to remove the matched items by replacing them with an empty string."
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 1,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json b/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json
deleted file mode 100644
index 4127daaeee..0000000000
--- a/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json
+++ /dev/null
@@ -1,2542 +0,0 @@
-{
- "name": "Bootstrap",
- "order": 2,
- "time": "5 hours",
- "helpRoom": "Help",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css"
- }
- ],
- "challenges": [
- {
- "id": "bad87fee1348bd9acdeb9212",
- "title": "Introduction to the Bootstrap Challenges",
- "description": [
- "",
- "",
- "Bootstrap is a front-end framework used to design responsive web pages and web applications. It takes a mobile-first approach to web development. Bootstrap includes pre-built CSS styles and classes, plus some JavaScript functionality.",
- "",
- "@@STEP@@",
- "",
- "",
- "Bootstrap uses a responsive 12 column grid layout and has design templates for:
This section introduces some of the ways to use Bootstrap in your web projects.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "",
- "challengeSeed": [],
- "tests": [],
- "type": "Waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "bad87fee1348bd9acde08712",
- "title": "Use Responsive Design with Bootstrap Fluid Containers",
- "description": [
- "In the HTML5 and CSS section of freeCodeCamp we built a Cat Photo App. Now let's go back to it. This time, we'll style it using the popular Bootstrap responsive CSS framework.",
- "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design
.",
- "With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.",
- "You can add Bootstrap to any app by adding the following code to the top of your HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"/>
",
- "In this case, we've already added it for you to this page behind the scenes. Note that using either >
or />
to close the link
tag is acceptable.",
- "To get started, we should nest all of our HTML (except the link
tag and the style
element) in a div
element with the class container-fluid
."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- "",
- "",
- "
",
- "
",
- "",
- "
",
- ""
- ],
- "tests": [
- "assert($(\"div\").hasClass(\"container-fluid\"), 'message: Your div
element should have the class container-fluid
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/style
tag in .container-fluid
.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Usa diseño adaptativo con los contenedores fluidos de Bootstrap",
- "description": [
- "Ahora vamos de vuelta a nuestra aplicación de fotos de gatos. Esta vez, vamos a darle estilo utilizando la infraestructura CSS del popular Bootstrap.",
- "Bootstrap determina qué tan ancha es la pantalla y adapta correspondientemente el tamaño de tus elementos HTML - por eso es que se llama Diseño adaptativo
(responsive design).",
- "Con diseño adaptativo, no hay necesidad de diseñar una versión móvil para tu sitio web. Se verá bien en dispositivos con pantallas de cualquier tamaño.",
- "Puedes agregar Bootstrap a cualquier aplicación simplemente incluyendo el siguiente código al inicio de tu HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/>
",
- "En este caso, lo hemos agregado a esta página por ti.",
- "Para iniciar, debemos anidar todo nuestro HTML en un elemento div
con la clase container-fluid
."
- ]
- },
- "fr": {
- "title": "Un design adaptatif (responsive design) utilisant les conteneurs fluides de Bootstrap",
- "description": [
- "Revenons à notre application de photos de chats. Cette fois-ci, nous allons lui donner un style grâce au renommé framework CSS Bootstrap.",
- "Bootstrap saura reconnaître la largeur de notre écran et s'y adapter en redimensionnant les éléments HTML - d'où le nom Responsive Design
(design adaptatif).",
- "Avec le design responsive, il n'y a pas besoin de créer de version mobile de votre site. Il restera bien sur tous les appareils quelle que soit la taille de leurs écrans.",
- "Vous pouvez ajouter Bootstrap à n'importe quelle application simplement en incluant le code suivant en haut de votre HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\" integrity=\"sha384-8+rznmq/k0KZkJlZhnuPEVkbRD7tA0wcFEjY48dajGWn3Xc1MasJwS8/tJ7OEsKW\" crossorigin=\"anonymous\">/>
",
- "Ici, nous l'avons déjà ajouté à la page pour vous dans l'arrière-boutique.",
- "Pour commencer, nous devons envelopper nos éléments HTML dans un élément div
possédant la classe container-fluid
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9acde08812",
- "title": "Make Images Mobile Responsive",
- "description": [
- "First, add a new image below the existing one. Set its src
attribute to https://bit.ly/fcc-running-cats
.",
- "It would be great if this image could be exactly the width of our phone's screen.",
- "Fortunately, with Bootstrap, all we need to do is add the img-responsive
class to your image. Do this, and the image should perfectly fit the width of your page."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "img-responsive
.');",
- "assert(!$(\"img:eq(1)\").hasClass(\"smaller-image\"), 'message: Your new image should not have the class smaller-image
.');",
- "assert($(\"img:eq(1)\").attr(\"src\") === \"https://bit.ly/fcc-running-cats\", 'message: Your new image should have a src
of https://bit.ly/fcc-running-cats
.');",
- "assert(code.match(//g).length === 2 && code.match(/
img element has a closing angle bracket.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Haz que las imágenes sean adaptativas en dispositivos móviles",
- "description": [
- "Primero, agrega una nueva imagen debajo que la que ya existe. Haz que su atributo
src
sea https://bit.ly/fcc-running-cats
.",
- "Sería genial si esta imagen fuera exactamente del tamaño de la pantalla de nuestro teléfono.",
- "Afortunadamente, con Bootstrap, todo lo que tenemos que hacer es agregar la clase img-responsive
a tu imagen. Hazlo, y verás que la imagen se ajustará perfectamente al ancho de tu página."
- ]
- },
- "fr": {
- "title": "Rendre des images adaptatives aux appareils mobiles",
- "description": [
- "It would be great if this image could be exactly the width of our phone's screen.",
- "Fortunately, with Bootstrap, all we need to do is add the img-responsive
class to your image. Do this, and the image should perfectly fit the width of your page.",
- "D'abord, ajoutez une nouvelle image en dessous de celle qui eiste dejà. Changez l'attribut src en
elements have a closing tag.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Crea un botón con Bootstrap",
- "description": [
- "Bootstrap tiene sus propios estilos para elementos https://bit.ly/fcc-running-cats
.",
- "Ce serait absolument super si notre image pouvait être exactement de la largeur de l'écran du téléphone.",
- "Heureusement, avec Bootstrap, il faut seulement ajouter la classe img-responsive
à notre image. Faites le, et l'image devrait s'ajuster parfaitement à la largeur de la page."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd8acde08812",
- "title": "Center Text with Bootstrap",
- "description": [
- "Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class text-center
to our h2
element.",
- "Remember that you can add several classes to the same element by separating each of them with a space, like this:",
- "<h2 class=\"red-text text-center\">your text</h2>
"
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "h2
element should be centered by applying the class text-center
');",
- "assert($(\"h2\").hasClass(\"red-text\"), 'message: Your h2
element should still have the class red-text
');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Centra el texto con Bootstrap",
- "description": [
- "Ahora que estamos usando Bootstrap, podemos centrar nuestro elemento de encabezado para hacerlo verse mejor. Todo lo que necesitamos hacer es agregar la clase text-center
a nuestro elemento h2
.",
- "Recuerda que puedes agregar varias clases a un mismo elemento separando cada una de ellas con un espacio, de esta forma:",
- "<h2 class=\"red-text text-center\">your text</h2>
"
- ]
- },
- "fr": {
- "title": "Centrer du texte avec Bootstrap",
- "description": [
- "Maintenant que wous utilisons Bootstrap, nous pouvons centrer notre entête pour qu'il ait une meilleure apparence. Nous devons seulement ajouter la classe text-center
à notre élément h2
.",
- "Souvenez vous que vous pouvez utiliser plusieurs classes pour un même élément en les séparant avec un espace, comme ceci:",
- "<h2 class=\"red-text text-center\">Votre texte</h2>
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348cd8acdf08812",
- "title": "Create a Bootstrap Button",
- "description": [
- "Bootstrap has its own styles for button
elements, which look much better than the plain HTML ones.",
- "Create a new button
element below your large kitten photo. Give it the class btn
and the text of \"Like\"."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "button
element with the text \"Like\".');",
- "assert($(\"button\").hasClass(\"btn\"), 'message: Your new button should have the class btn
.');",
- "assert(code.match(/<\\/button>/g) && code.match(/button
, los cuales se ven mejor que los estilos simples de HTML.",
- "Crea un nuevo elemento button
debajo de tu foto grande del gatito. Dale la clase btn
y el texto \"Like\"."
- ]
- },
- "fr": {
- "title": "Créer un bouton avec Bootstrap",
- "description": [
- "Bootstrap possède ses propres styles pour les éléments button
, qui sont beaucoup plus beaux que ceux issus du HTML seul.",
- "Créez un nouvel élément button
en dessous de votre grande photo de chaton. Donnez lui comme classe btn
et comme texte \"Like\"."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348cd8acef08812",
- "title": "Create a Block Element Bootstrap Button",
- "description": [
- "Normally, your button
elements with a class of btn
are only as wide as the text that they contain. For example:",
- "<button class=\"btn\">Submit</button>
",
- "This button would only be as wide as the word \"Submit\".",
- "btn-block
, your button will stretch to fill your page's entire horizontal space and any elements following it will flow onto a \"new line\" below the block.",
- "<button class=\"btn btn-block\">Submit</button>
",
- "This button would take up 100% of the available width.",
- "btn
class.",
- "Add Bootstrap's btn-block
class to your Bootstrap button."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "btn
.');",
- "assert($(\"button\").hasClass(\"btn-block\"), 'message: Your button should have the class btn-block
.');",
- "assert(code.match(/<\\/button>/g) && code.match(/button
con una clase de btn
sólo son tan ancha como el texto que contienen. Por ejemplo:",
- "<button class=\"btn\">Enviar</button>
",
- "Este botón sólo sería tan amplia como la palabra \"Enviar\"",
- "btn-block
, el botón se amplía para llenar toda espacio horizontal de la página y los elementos siguientes fluirá sobre una \"nueva línea\" debajo del bloque .",
- "<button class=\"btn btn-block\">Enviar</button>
",
- "Este botón llevaría hasta el 100% de la anchura disponible.",
- "btn
.",
- "Agrega la clase de Bootstrap btn-block
a tu botón Bootstrap."
- ]
- },
- "fr": {
- "title": "Créer un bouton bloc Bootstrap",
- "description": [
- "Normalement , vos éléments de button
avec une classe de btn
ne sont aussi larges que le texte qu'ils contiennent . Par exemple:",
- "<button class=\"btn\">Soumettre</button>
",
- "Ce bouton ne serait plus large que le mot \"Soumettre\" .",
- "btn-block
, votre bouton étirer pour remplir tout l'espace horizontal de votre page et tous les éléments suivants, il coulera sur une \"nouvelle ligne\" en dessous du bloc .",
- "<button class=\"btn btn-block\">Soumettre</button>
",
- "Ce bouton prendrait 100% de la largeur disponible .",
- "btn
",
- "Ajoutez la classe Bootstrap btn-block
à votre bouton Bootstrap."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348cd8acef08811",
- "title": "Taste the Bootstrap Button Color Rainbow",
- "description": [
- "The btn-primary
class is the main color you'll use in your app. It is useful for highlighting actions you want your user to take.",
- "Add Bootstrap's btn-primary
class to your button.",
- "Note that this button will still need the btn
and btn-block
classes."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "btn-primary
.');",
- "assert($(\"button\").hasClass(\"btn-block\") && $(\"button\").hasClass(\"btn\"), 'message: Your button should still have the btn
and btn-block
classes.');",
- "assert(code.match(/<\\/button>/g) && code.match(/btn-primary
es el color principal que utilizarás en tu aplicación. Es útil resaltar las acciones que quieres que tu usuario ejecute.",
- "Agrega la clase btn-primary
de Bootstrap a tu botón.",
- "Ten en mente que este botón todavía necesita las clases btn
y btn-block
."
- ]
- },
- "fr": {
- "title": "Goutez à l'arc en ciel de couleurs des boutons de Bootstrap",
- "description": [
- "La classe btn-primary
est la couleur principale que vous utiliserez dans votre application. Elle est utile pour mettre en valeur les actions que vous voulez faire réaliser par vos utilisateurs.",
- "Ajoutez la classe Bootstrap btn-primary
à votre bouton.",
- "Notez que ce bouton a toujours besoin des classes btn
et btn-block
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348cd8acef08813",
- "title": "Call out Optional Actions with btn-info",
- "description": [
- "Bootstrap comes with several pre-defined colors for buttons. The btn-info
class is used to call attention to optional actions that the user can take.",
- "Create a new block-level Bootstrap button below your \"Like\" button with the text \"Info\", and add Bootstrap's btn-info
and btn-block
classes to it.",
- "Note that these buttons still need the btn
and btn-block
classes."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "button
element with the text \"Info\".');",
- "assert($(\"button.btn-block.btn\").length > 1, 'message: Both of your Bootstrap buttons should have the btn
and btn-block
classes.');",
- "assert($(\"button\").hasClass(\"btn-info\"), 'message: Your new button should have the class btn-info
.');",
- "assert(code.match(/<\\/button>/g) && code.match(/btn-info
se utiliza para llamar la atención a acciones opcionales que el usuario puede tomar.",
- "Crea un nuevo botón a nivel de bloque de Bootstrap debajo de tu botón de \"Like\" con el texto \"Info\", y agrégale las clases de Bootstrap btn-info
y btn-block
.",
- "Ten en mente que estos botones todavía necesitan las clases btn
y btn-block
."
- ]
- },
- "fr": {
- "title": "Indiquez les actions optionelles avec des boutons informatifs",
- "description": [
- "Bootstrap est livré avec plusieurs couleurs prédéfinies pour les boutons. La classe btn-info
est utilisée pour indiquer des actions optionelles pour vos utilisateurs.",
- "Créez un nouveau bouton Bootstrap bloc en dessous de votre bouton \"Like\" avec le texte \"Info\" et donnez lui les classes Bootstrap btn-info
et btn-block
.",
- "Notez que ces boutons ont toujours besoins des classes btn
and btn-block
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348ce8acef08814",
- "title": "Warn Your Users of a Dangerous Action with btn-danger",
- "description": [
- "Bootstrap comes with several pre-defined colors for buttons. The btn-danger
class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.",
- "Create a button with the text \"Delete\" and give it the class btn-danger
.",
- "Note that these buttons still need the btn
and btn-block
classes."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "button
element with the text \"Delete\".');",
- "assert($(\"button.btn-block.btn\").length > 2, 'message: All of your Bootstrap buttons should have the btn
and btn-block
classes.');",
- "assert($(\"button\").hasClass(\"btn-danger\"), 'message: Your new button should have the class btn-danger
.');",
- "assert(code.match(/<\\/button>/g) && code.match(/btn-danger
es el color de botón que usarías para notificar a los usuarios que el botón ejecuta una acción destructiva, como por ejemplo eliminar la foto de un gato.",
- "Crea un botón con el texto \"Delete\" y dale la clase btn-danger
.",
- "Recuerda que estos botones todavía requieren las clases btn y
elements has a closing tag.');",
- "assert(code.match(/<\\/div>/g) && code.match(/btn-block
."
- ]
- },
- "fr": {
- "title": "Prévenez vos utilisateurs d'une action dangereuse",
- "description": [
- "Bootstrap est livré avec plusieurs couleurs prédéfinies pour les boutons. La classe btn-danger
est utilisée pour indiquer aux utilisateurs que le bouton actionne un processus destructif comme supprimer une photo de chat.",
- "Créez un bouton ayant le texte \"Delete\" et donnez lui la classe btn-danger
.",
- "Notez que ces boutons ont toujours besoins des classes btn
and btn-block
."
- ]
- }
- }
- },
- {
- "id": "bad88fee1348ce8acef08815",
- "title": "Use the Bootstrap Grid to Put Elements Side By Side",
- "description": [
- "Bootstrap uses a responsive 12-column grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div
element.",
- "Bootstrap has different column width attributes that it uses depending on how wide the user's screen is. For example, phones have narrow screens, and laptops have wider screens.",
- "Take for example Bootstrap's col-md-*
class. Here, md
means medium, and *
is a number specifying how many columns wide the element should be. In this case, the column width of an element on a medium-sized screen, such as a laptop, is being specified.",
- "In the Cat Photo App that we're building, we'll use col-xs-*
, where xs
means extra small (like an extra-small mobile phone screen), and *
is the number of columns specifying how many columns wide the element should be.",
- "Put the Like
, Info
and Delete
buttons side-by-side by nesting all three of them within one <div class=\"row\">
element, then each of them within a <div class=\"col-xs-4\">
element.",
- "The row
class is applied to a div
, and the buttons themselves can be nested within it."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "div
element with the class row
.');",
- "assert($(\"div.col-xs-4:has(button)\").length > 2, 'message: Each of your Bootstrap buttons should be nested within its own div
element with the class col-xs-4
.');",
- "assert(code.match(/<\\/button>/g) && code.match(/div
.",
- "Aquí hay un diagrama del funcionamiento de la cuadrícula de 12 columnas Bootstrap:",
- "",
- "En esta ilustración se está utilizando la clase
col-md-*
. Aquí, md
significa mediano, y *
es un número que especifica la cantidad de columnas debe tomar el ancho del elemento. En este caso, se especifica el ancho de columna de un elemento en una pantalla de tamaño mediano, como una laptop.",
- "En la aplicación de fotos de gatos que estamos construyendo, usaremos col-xs-*
, donde xs
significa extra pequeño (como una pantalla extra-pequeña de un teléfono), y *
especifica el número de columnas que debe tomar el ancho del elemento.",
- "Pon los botones de Like
, Info
y Delete
lado a lado. Esto se hace anidando los tres botones dentro de un elemento <div class=\"row\">
, y luego cada uno de ellos dentro de un elemento <div class=\"col-xs-4\">
.",
- "La clase row
se aplica al elemento div
, dentro del cual van anidados los botones."
- ]
- },
- "fr": {
- "title": "Utilisez la grille de Bootstrap pour mettre les éléments côte-à-côte.",
- "description": [
- "Bootstrap utilise un système de grille adaptative, qui rend plus simple le placement des éléments en rangées et la spécification de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être associés à un élément div
",
- "Voici un diagramme décrivant le fonctionnement du système de grille à 12 colonnes:",
- "",
- "Notez que dans cet exemple, nous avons utilisé la classe
col-md-*
. Ici, md
signifie medium, et *
donne le nombre de colonnes en largeur de l'élément. Dans le cas présenté, on a défini la largeur en colonnes d' un élément sur un écrand de taille medium, comme un ordinateur portable.",
- "Dans l'application de photos de chats que nous sommes en train de construire, nous utiliserons col-xs-*
, où xs
signifie extrêmement petit (comme un écran de téléphone mobile), et *
est le nombre de colonnes en largeur de l'élément.",
- "Mettez les boutons Like
, info
et Delete
côte-à-côte en les enveloppant tous dans un élément <div class=\"row\">
, puis chacun d'entre eux dans un élément <div class=\"col-xs-4\">
element.",
- "La classe row
est donnée à un div
, et les boutons peuvent être insérés à l'intérieur de celui-ci."
- ]
- }
- }
- },
- {
- "id": "bad87fee1347bd9aedf08845",
- "title": "Ditch Custom CSS for Bootstrap",
- "description": [
- "We can clean up our code and make our Cat Photo App look more conventional by using Bootstrap's built-in styles instead of the custom styles we created earlier.",
- "Don't worry - there will be plenty of time to customize our CSS later.",
- "Delete the .red-text
, p
, and .smaller-image
CSS declarations from your style
element so that the only declarations left in your style
element are h2
and thick-green-border
.",
- "Then delete the p
element that contains a dead link. Then remove the red-text
class from your h2
element and replace it with the text-primary
Bootstrap class.",
- "Finally, remove the \"smaller-image\" class from your first img
element and replace it with the img-responsive
class."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "red-text
.');",
- "assert($(\"h2\").hasClass(\"text-primary\"), 'message: Your h2 element should now have the class text-primary
.');",
- "assert(!$(\"p\").css(\"font-family\").match(/monospace/i), 'message: Your paragraph elements should no longer use the font Monospace
.');",
- "assert(!$(\"img\").hasClass(\"smaller-image\"), 'message: Remove the smaller-image
class from your top image.');",
- "assert($(\".img-responsive\").length > 1, 'message: Add the img-responsive
class to your top image.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Reemplaza el CSS personalizado por Bootstrap",
- "description": [
- "Podemos limpiar nuestro código y hacer que nuestra aplicación de fotos de gatos se vea más convencional, usando los estilos pre-construidos de Bootstrap, en lugar de los estilos personalizados que creamos antes.",
- "No te preocupes, luego habrá más tiempo para personalizar nuestro CSS.",
- "Elimina las declaraciones CSS .red-text
, p
, y .smaller-image
de tu elemento style
, de forma que las únicas declaraciones que queden en tu elemento style
sean h2
y thick-green-border
.",
- "Luego elimina el elemento p
que contiene un enlace nulo. Después, elimina la clase red-text
de tu elemento h2
y reemplázalo con la clase text-primary
de Bootstrap.",
- "Por último, elimina la clase \"smaller-image\" de tu primer elemento img
y reemplázalo con la clase img-responsive
."
- ]
- },
- "fr": {
- "title": "Remplacez le CSS personnalisé par les styles Bootstrap",
- "description": [
- "Nous pouvons nettoyer notre code et rendre le look de notre appli Cat Photos plus conventionnel en utilisant les styles intégrés à Bootstrap à la place des styles personnalisés que nous avons créés auparavant.",
- "Ne vous inquiétez pas - nous auront beaucoup de temps pour personnaliser notre CSS plus tard.",
- "Supprimez les déclarations CSS .red-text
, p
, et .smaller-image
de votre élément style
pour que les seules déclarations restantes dans l'élément style
soient h2
et thick-green-border
.",
- "Ensuite supprimez l'élément p
contenant un lien fantôme. Puis enlevez la classe red-text
de votre élément h2
et remplacez la par la classe Bootstrap text-primary
",
- "Enfin, enlevez la classe \"smaller-image\" dde votre premier élément img
et remplacez le par la classe img-responsive
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aedf08845",
- "title": "Use a span to Target Inline Elements",
- "description": [
- "You can use spans to create inline elements. Remember when we used the btn-block
class to make the button fill the entire row?",
- "span
element, you can put several elements on the same line, and even style different parts of the same line differently.",
- "Nest the word \"love\" in your \"Things cats love\" element below within a span
element. Then give that span
the class text-danger
to make the text red.",
- "Here's how you would do this with the \"Top 3 things cats hate\" element:",
- "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>
"
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "span
element should be inside your p
element.');",
- "assert($(\"p span\") && $(\"p span\").text().match(/love/i) && !$(\"p span\").text().match(/Things cats/i), 'message: Your span
element should have just the text love
.');",
- "assert($(\"span\").hasClass(\"text-danger\"), 'message: Your span
element should have class text-danger
.');",
- "assert(code.match(/<\\/span>/g) && code.match(//g).length === code.match(/span element has a closing tag.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Usa span para elementos en línea",
- "description": [
- "Puedes utilizar span para crear elementos en línea. ¿Recuerdas cuando usamos la clase btn-block
para hacer que el botón llenara toda la línea?",
- "Esta imagen ilustra la diferencia entre elementos en línea (inline
) y elementos a nivel de bloque (block-level
):",
- "",
- "Al usar el elemento
span
, puedes poner varios elementos juntos, e incluso darle diferentes estilos a partes diferentes del mismo elemento.",
- "Anida la palabra \"love\" en tu elemento \"Things cats love\" dentro de un elemento span
. Luego, asigna a ese elemento span
la clase text-danger
para hacer que el texto sea rojo.",
- "Así es como lo harías con el elemento \"Top 3 things cats hate\":",
- "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>
"
- ]
- },
- "fr": {
- "title": "Utiliser Spans pour les éléments \"Inline\"",
- "description": [
- "Vous pouvez utiliser les spans pour créer des éléments inline. Vous rappelez vous quand nous avions utilisé la classe btn-block
pour remplir la rangée entière?",
- "Cette image illustre la différence entre les éléments inline
(en ligne) et les éléments block-level
(de blocs):",
- "",
- "En utilisant un élément
span
, vous pouvez mettre ensemble plusieurs éléments, et même donner un style différent à plusieurs parties d'un même élément",
- "Nichez le mot \"love\" dans votre élément \"Things cats love\" en dessous dans un élément span
; Ensuite donnez à ce span
la classe text-danger
pour rendre le texte rouge.",
- "Il faudrait que vous fassiez ainsi pour l'élément \"Top 3 things cats hate\":",
- "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aede08845",
- "title": "Create a Custom Heading",
- "description": [
- "We will make a simple heading for our Cat Photo App by putting the title and relaxing cat image in the same row.",
- "Remember, Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div
element.",
- "Take for example Bootstrap's col-md-*
class. Here, md
means medium, and *
is a number specifying how many columns wide the element should be. In this case, the column width of an element on a medium-sized screen, such as a laptop, is being specified.",
- "In the Cat Photo App that we're building, we'll use col-xs-*
, where xs
means extra small (like an extra-small mobile phone screen), and *
is the number of columns specifying how many columns wide the element should be.",
- "Put the Like
, Info
and Delete
buttons side-by-side by nesting all three of them within one <div class=\"row\">
element, then each of them within a <div class=\"col-xs-4\">
element.",
- "In the Cat Photo App that we're building, we'll use col-xs-*
, where xs
means extra small (like an extra-small mobile phone screen), and *
is the number of columns specifying how many columns wide the element should be.",
- "Nest your first image and your h2
element within a single <div class=\"row\">
element. Nest your h2
element within a <div class=\"col-xs-8\">
and your image in a <div class=\"col-xs-4\">
so that they are on the same line.",
- "Notice how the image is now just the right size to fit along the text?"
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "CatPhotoApp
",
- "",
- " ",
- "",
- "
",
- "
",
- "
",
- " ",
- "
",
- " ",
- "h2
element and topmost img
element should both be nested together within a div
element with the class row
.');",
- "assert($(\"div.col-xs-4:has(img)\").length > 0 && $(\"div.col-xs-4:has(div)\").length === 0, 'message: Nest your topmost img
element within a div
with the class col-xs-4
.');",
- "assert($(\"div.col-xs-8:has(h2)\").length > 0 && $(\"div.col-xs-8:has(div)\").length === 0, 'message: Nest your h2
element within a div
with the class col-xs-8
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/div
.",
- "Aquí hay un diagrama del funcionamiento de la cuadrícula de 12 columnas Bootstrap:",
- "",
- "En esta ilustración se está utilizando la clase
col-md-*
. Aquí, md
significa mediano, y *
es un número que especifica el número de columnas que debe tomar el ancho del elemento. En este caso, se especifica el ancho de columna de un elemento en una pantalla de tamaño mediano, como un computador portátil.",
- "En la aplicación de fotos de gatos que estamos construyendo, usaremos col-xs-*
, donde xs
significa extra pequeño (como una pantalla extra-pequeña de un teléfono), y *
especifica el número de columnas que debe tomar el ancho del elemento.",
- "Anida tu primera imagen y tu elemento h2
dentro de un solo elemento <div class=\"row\">
. Anida tu texto h2
dentro de un <div class=\"col-xs-8\">
y tu imagen en un <div class=\"col-xs-4\">
de tal forma que estén en la misma línea.",
- "¿Te diste cuenta de que la imagen es ahora justamente del tamaño apropiado para el texto?"
- ]
- },
- "fr": {
- "title": "Créer un entête personalisé",
- "description": [
- "Notice how the image is now just the right size to fit along the text?",
- "Nous allons réaliser un entête tout simple pour notre appli Cat Photo App en plaçant le titre et l'image de chat relaxante dans la même rangée.",
- "Rappelez-vous, Bootstrap utilise un système de grille adaptative, qui rend facile le placement des éléments en rangées et la définition de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être appliquées à un élément div
.",
- "Voici un diagramme du fonctionnement de la grille à 12 colonnes de Bootstrap:",
- "",
- "Notez que dans cet exemple, on utilise la classe
col-md-*
. Ici md
signifie medium, et *
est un nombre spécifiant le nombre de colonnes en largeur que l'élément devrait avoir.",
- "Enveloppez votre première image et votre élément h2
dans un seul élément <div class=\"row\">
. Mettez l'élément h2
dans un <div class=\"col-xs-8\">
et votre image dans un <div class=\"col-xs-4\">
pour qu'ils soient sur la même ligne.",
- "Voyez vous comme l'image est maintenant exactement ajustée à la bonne taille pour être à côté du texte?"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aedd08845",
- "title": "Add Font Awesome Icons to our Buttons",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg
file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.",
- "You can include Font Awesome in any app by adding the following code to the top of your HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\">
",
- "In this case, we've already added it for you to this page behind the scenes.",
- "The i
element was originally used to make other elements italic, but is now commonly used for icons. You can add the Font Awesome classes to the i
element to turn it into an icon, for example:",
- "<i class=\"fa fa-info-circle\"></i>
",
- "Note that the span
element is also acceptable for use with icons.",
- "Use Font Awesome to add a thumbs-up
icon to your like button by giving it an i
element with the classes fa
and fa-thumbs-up
; make sure to keep the text \"Like\" next to the icon."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "i
element with the classes fa
and fa-thumbs-up
.');",
- "assert(($(\"i.fa-thumbs-up\").parent().text().match(/Like/gi) && $(\".btn-primary > i\").is(\".fa.fa-thumbs-up\")) || ($(\"span.fa-thumbs-up\").parent().text().match(/Like/gi) && $(\".btn-primary > span\").is(\".fa.fa-thumbs-up\")), 'message: Your fa-thumbs-up
icon should be located within the Like button.');",
- "assert($(\"button\").children(\"i\").length > 0 || $(\"button\").children(\"span\").length > 0, 'message: Nest your i
element within your button
element.');",
- "assert(code.match(/<\\/i>|<\\/span>/g), 'message: Make sure your icon element has a closing tag.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Agrega iconos de Font Awesome a los botones",
- "description": [
- "Font Awesome es una librería de iconos muy conveniente. Estos iconos son imágenes vectoriales, almacenadas en formato .svg
, y son tratados como si fueran fuentes. Puedes especificar su tamaño usando pixeles, y tomarán el tamaño de fuente de su elemento HTML padre.",
- "Puedes añadir Font Awesome a cualquier aplicación sólo incluyendo y agregando el siguiente código al comienzo de tu HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\"/>
",
- "En este caso, ya lo hemos agregado por tí a esta página tras bambalinas.",
- "El elemento i
originalmente era usado para hacer textos en itálicas, pero ahora comunmente se usa para iconos. Le agregas clases de Font Awesome al elemento i
para convertirlo en un ícono, por ejemplo:",
- "<i class=\"fa fa-info-circle\"></i>
",
- "Usa Font Awesome para agregar un icono de \"pulgar arriba\" thumbs-up
a tu botón de like dándole un elemento i
con las clases fa
y fa-thumbs-up
."
- ]
- },
- "fr": {
- "title": "Ajouter des icônes Font Awesome à nos boutons",
- "description": [
- "Font Awesome est une librairie d'icônes très pratique. Ces icones sont des images vectorielles, stockées en format .svg
. Ces icônes sont traités exactemeent comme des polices. Vous pouvez choisir leur taille en pixel, et ils prendront la taille de police de leur élémment parent HTML.",
- "Vous poyvez ajouter Font Awesome à n'importe quell application en ajoutant le code suivant en haut de votre HTML:",
- "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\">/>
",
- "Ici, nous l'avons déjà ajouté pour vous dans le back-office.",
- "La balise i
eétait utilisé à la base pour mettre les autres éléments en italique, mais maintenant elle est utilisée pour les icones. Vous ajoutez des classes Font Awesome à un élément i
pour les les transformer en icones, par exemple:",
- "<i class=\"fa fa-info-circle\"></i>
",
- "Utilisez Font Awesome pour ajouter un icone thumbs-up
à votre bouton de like en lui donnant un élément i
ayant les classes fa
et fa-thumbs-up
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aedc08845",
- "title": "Add Font Awesome Icons to all of our Buttons",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg
file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.",
- "Use Font Awesome to add an info-circle
icon to your info button and a trash
icon to your delete button.",
- "Note: The span
element is an acceptable alternative to the i
element for the directions below."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "<i class=\"fa fa-info-circle\"></i>
within your info button element.');",
- "assert($(\".btn-danger > i\").is(\".fa.fa-trash\") || $(\".btn-danger > span\").is(\".fa.fa-trash\"), 'message: You should add a <i class=\"fa fa-trash\"></i>
within your delete button element.');",
- "assert(code.match(/<\\/i>|<\\/span/g) && code.match(/<\\/i|<\\/span>/g).length > 2 && ($(\".btn-primary > i\").is(\".fa.fa-thumbs-up\") || $(\".btn-primary > span\").is(\".fa.fa-thumbs-up\")), 'message: Make sure each of your i
elements has a closing tag and <i class=\"fa fa-thumbs-up\"></i>
is in your like button element.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Agrega Font Awesome a todos los botones",
- "description": [
- "Font Awesome es una librería de iconos muy conveniente. Estos iconos son imágenes vectoriales, almacenadas en formato .svg
, y son tratados como si fueran fuentes. Puedes especificar su tamaño usando pixeles, y tomarán el tamaño de fuente de su elemento HTML padre.",
- "Utiliza Font Awesome para agregar un icono info-circle
a tu botón informativo y un icono trash
a tu botón de eliminar."
- ]
- },
- "fr": {
- "title": "Ajoutez des icones Font Awesome à tous nos boutons",
- "description": [
- "Font Awesome est une librairie d'icônes très pratique. Ces icones sont des images vectorielles, stockées en format .svg
. Ces icônes sont traités exactemeent comme des polices. Vous pouvez choisir leur taille en pixel, et ils prendront la taille de police de leur élémment parent HTML.",
- "Utilisez Font Awesome pour ajouter un icone info-circle
à votre bouton d'info et un icone trash
à votre bouton de suppression."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aedb08845",
- "title": "Responsively Style Radio Buttons",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "You can use Bootstrap's col-xs-*
classes on form
elements, too! This way, our radio buttons will be evenly spread out across the page, regardless of how wide the screen resolution is.",
- "Nest both your radio buttons within a <div class=\"row\">
element. Then nest each of them within a <div class=\"col-xs-6\">
element.",
- "Note: As a reminder, radio buttons are input
elements of type radio
."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "div
with the class row
.');",
- "assert($(\"div.col-xs-6:has(input[type=\\\"radio\\\"])\").length > 1, 'message: Nest each of your radio buttons inside its own div
with the class col-xs-6
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/col-xs-*
de Bootstrap en elementos form
también! De esta forma, nuestros botones de opción estarán igualmente distribuidos en la página, sin importar qué tan ancha es la resolución de la pantalla.",
- "Anida todos los botones de opción dentro de un elemento <div class=\"row\">
. Luego, anida cada uno de ellos dentro de un elemento <div class=\"col-xs-6\">
."
- ]
- },
- "fr": {
- "title": "Donnez un style responsive à vos boutons radio",
- "description": [
- "Vous pouvez utiliser la classe Bootstrap col-xs-*
sur des éléments form
. Comme ça, nos boutons radio serons disposés régulierement dans la page, quelle que soit la largeur de l'écran.",
- "Nichez tous vous boutons radio dans un élément <div class=\"row\">
. Ensuite, nichezchacun d'entre eux dans un élément <div class=\"col-xs-6\">
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aeda08845",
- "title": "Responsively Style Checkboxes",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "You can use Bootstrap's col-xs-*
classes on form
elements, too! This way, our checkboxes will be evenly spread out across the page, regardless of how wide the screen resolution is.",
- "Nest all three of your checkboxes in a <div class=\"row\">
element. Then nest each of them in a <div class=\"col-xs-4\">
element."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "div
with the class row
.');",
- "assert($(\"div.col-xs-4:has(input[type=\\\"checkbox\\\"])\").length > 2, 'message: Nest each of your checkboxes inside its own div
with the class col-xs-4
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/col-xs-*
de Bootstrap en elementos form
también! De esta forma, nuestros botones de opción estarán igualmente distribuidos en la página, sin importar qué tan ancha es la resolución de la pantalla.",
- "Anida todas las casillas de selección en un elemento <div class=\"row\">
. Luego, anida cada una de ellas en un elemento <div class=\"col-xs-4\">
."
- ]
- },
- "fr": {
- "title": "Donnez un style responsive à vos checkbox (cases de séléction)",
- "description": [
- "Vous pouvez aussi utiliser la classe Bootstrap col-xs-*
sur des éléments form
! Comme ça, nos boutons radio serons disposés régulierement dans la page, quelle que soit la largeur de l'écran.",
- "You can use Bootstrap's col-xs-*
classes on form
elements, too! This way, our checkboxes will be evenly spread out across the page, regardless of how wide the screen resolution is.",
- "Nichez toustes vos checkbox dans un élément <div class=\"row\">
. Ensuite nichez chacun d'entre eux dans un élément <div class=\"col-xs-4\">
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aed908845",
- "title": "Style Text Inputs as Form Controls",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "You can add the fa-paper-plane
Font Awesome icon by adding <i class=\"fa fa-paper-plane\"></i>
within your submit button
element.",
- "Give your form's text input field a class of form-control
. Give your form's submit button the classes btn btn-primary
. Also give this button the Font Awesome icon of fa-paper-plane
.",
- "All textual <input>
, <textarea>
, and <select>
elements with the class .form-control
have a width of 100%."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "btn btn-primary
.');",
- "assert($(\"button[type=\\\"submit\\\"]:has(i.fa.fa-paper-plane)\").length > 0, 'message: Add a <i class=\"fa fa-paper-plane\"></i>
within your submit button
element.');",
- "assert($(\"input[type=\\\"text\\\"]\").hasClass(\"form-control\"), 'message: Give the text input
in your form the class form-control
.');",
- "assert(code.match(/<\\/i>/g) && code.match(/<\\/i/g).length > 3, 'message: Make sure each of your i
elements has a closing tag.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Estiliza cajas de texto como controles de formulario",
- "description": [
- "Puedes agregar el icono fa-paper-plane
de Font Awesome incluyendo <i class=\"fa fa-paper-plane\"></i>
dentro de tu elemento button
de envío.",
- "Dale a la entrada de texto de tu formulario la clase form-control
. Dale al botón de envío de tu formulario las clases btn btn-primary
. También, incluye en ese botón el icono fa-paper-plane
de Font Awesome."
- ]
- },
- "fr": {
- "title": "Donnez un style similaire au contrôles de formulaires à des zones de texte",
- "description": [
- "Vous pouvez ajouter l'icone Font Awesome fa-paper-plane
en ajoutant <i class=\"fa fa-paper-plane\"></i>
à l'intérieur de votre button
de soumission du formulaire.",
- "Donnez aux entrées texte de votre formulaire une classe form-control
. Donnez à votre bouton de soumission de formulaire les classes btn btn-primary
. Donnez lui aussi un icone Font Awesome fa-paper-plane
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908845",
- "title": "Line up Form Elements Responsively with Bootstrap",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css",
- "raw": true
- }
- ],
- "description": [
- "Now let's get your form input
and your submission button
on the same line. We'll do this the same way we have previously: by using a div
element with the class row
, and other div
elements within it using the col-xs-*
class.",
- "Nest both your form's text input
and submit button
within a div
with the class row
. Nest your form's text input
within a div with the class of col-xs-7
. Nest your form's submit button
in a div
with the class col-xs-5
.",
- "This is the last challenge we'll do for our Cat Photo App for now. We hope you've enjoyed learning Font Awesome, Bootstrap, and responsive design!"
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "
",
- "
",
- " ",
- "
",
- " ",
- "row
.');",
- "assert($(\"div.col-xs-7:has(input[type=\\\"text\\\"])\").length > 0, 'message: Nest your form text input in a div with the class col-xs-7
.');",
- "assert($(\"div.col-xs-5:has(button[type=\\\"submit\\\"])\").length > 0, 'message: Nest your form submission button in a div with the class col-xs-5
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/input
y el elemento button
que dice submit de tu formulario en la misma línea. Lo haremos de la misma forma que lo hicimos anteriormente: usando un elemento div
con la clase row
, y otros elementos div
dentro de ese, usando la clase col-xs-*
.",
- "Anida ambos, el elemento input
y el elemento button
que dice submit de tu formulario dentro de un div
con la clase row
. Anida el elemento input
de tu formulario dentro de un div con cla clase col-xs-7
. Anida el elemento button
que dice submit de tu formulario en un elemento div
con la clase col-xs-5
.",
- "¡Este es el último desafío que haremos con nuestra aplicación de fotos de gato por ahora. Esperamos que hayas disfrutado aprender acerca de Font Awesome, Bootstrap y diseño adaptativo!"
- ]
- },
- "fr": {
- "title": "Aligner les éléments de formulaire de façon responsive avec Bootstrap",
- "description": [
- "Maintenant mettons sur la même ligne l'élément input
et le button
de soumission du formulaire. Nous procéderons de la même façon que précedemment: en utilisant un élément div
avec la classe row
, et un un autre div à l'intérieur qui aura la classe col-xs-*
.",
- "Nichez à la fois l'input
texte de votre formulaire et le button
de soumission de formulaire à l'intérieur d'un div
avec la classe row
. Nichez l'input
texte du formulaire dans un div ayant la classe col-xs-7
. Nichez votre button
de soumission de formulaire dans un div ayant la classe col-xs-5
.",
- "C'est le dernier challenge qui concerne notre application de photos de chats. Nous espérons que vous avez aimé apprendre Font Awesome, Bootstrap et du design adaptatif!"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908846",
- "title": "Create a Bootstrap Headline",
- "description": [
- "Now let's build something from scratch to practice our HTML, CSS and Bootstrap skills.",
- "We'll build a jQuery playground, which we'll soon put to use in our jQuery challenges.",
- "To start with, create an h3
element, with the text jQuery Playground
.",
- "Color your h3
element with the text-primary
Bootstrap class, and center it with the text-center
Bootstrap class."
- ],
- "challengeSeed": [
- "",
- "",
- ""
- ],
- "tests": [
- "assert($(\"h3\") && $(\"h3\").length > 0, 'message: Add a h3
element to your page.');",
- "assert(code.match(/<\\/h3>/g) && code.match(//g).length === code.match(/
h3 element has a closing tag.');",
- "assert($(\"h3\").hasClass(\"text-primary\"), 'message: Your
h3
element should be colored by applying the class text-primary
');",
- "assert($(\"h3\").hasClass(\"text-center\"), 'message: Your h3
element should be centered by applying the class text-center
');",
- "assert.isTrue((/jquery(\\s)+playground/gi).test($(\"h3\").text()), 'message: Your h3
element should have the text jQuery Playground
.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Crea un encabezado con Bootstrap",
- "description": [
- "Ahora vamos a comenzar un proyecto desde cero para practicar nuestras habilidades con HTML, CSS y Bootstrap.",
- "Crearemos un área de juego con jQuery, el cual utilizaremos en nuestros desafíos con jQuery.",
- "Para empezar, crea un elemento h3
, con el texto jQuery Playground
.",
- "Ponle color a tu elemento h3
con la clase text-primary
de Bootstrap, y céntrala con la clase text-center
de Bootstrap."
- ]
- },
- "fr": {
- "title": "Créer un entête Bootstrap",
- "description": [
- "Maintenons, créons queqlque chose à partir de zéro pour pratiquer nos connaissances acquises sur HTML, CSS et Bootstrap.",
- "Nous allons construire un terrain de jeu pour jQuery, que nous allons bientôt utiliser dans les challenges jQuery.",
- "Pour commencer, créez un élément h3
, contenant le texte jQuery Playground
.",
- "Colorez notre élément h3
avec la classe Bootstrap text-primary
, et centrez le en utilisant la classe Bootstrap text-center
"
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908746",
- "title": "House our page within a Bootstrap container-fluid div",
- "description": [
- "Now let's make sure all the content on your page is mobile-responsive.",
- "Let's nest your h3
element within a div
element with the class container-fluid
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- "",
- ""
- ],
- "tests": [
- "assert($(\"div\").hasClass(\"container-fluid\"), 'message: Your div
element should have the class container-fluid
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/h3
element inside a div
element.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Aloja la página dentro de un elemento Div contenedor fluido de Bootstrap",
- "description": [
- "Ahora asegurémonos de que todo el contenido en nuestra página pueda adaptarse a dispositivos móviles.",
- "Anida tu elemento h3
dentro de un elemento div
con la clase container-fluid
."
- ]
- },
- "fr": {
- "title": "Loger notre page dans un conteneur Bootstrap Fluid Div",
- "description": [
- "Maintenant, assurons nous que tout le contenu de la page est mobile-responsive (adaptatif au téléphones mobiles).",
- "Nichons notre element h3
à l'intérieur d'un élément div
ayant la classe container-fluid
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9bec908846",
- "title": "Create a Bootstrap Row",
- "description": [
- "Now we'll create a Bootstrap row for our inline elements.",
- "Create a div
element below the h3
tag, with a class of row
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- "",
- "div
element below your h3
element.');",
- "assert($(\"div\").hasClass(\"row\"), 'message: Your div
element should have the class row
');",
- "assert($(\"div.container-fluid div.row\").length > 0, 'message: Your row div
should be nested inside the container-fluid div
');",
- "assert(code.match(/<\\/div>/g) && code.match(/div
debajo de la etiqueta h3
, con la clase row
."
- ]
- },
- "fr": {
- "title": "Créer une rangée (row) Bootstrap",
- "description": [
- "Maintenant nous allons créer une rangée (row) Bootstrap pour nos éléments inline.",
- "Créez un élément div
en dessous de la balise h3
, avec une classe row
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908847",
- "title": "Split Your Bootstrap Row",
- "description": [
- "Now that we have a Bootstrap Row, let's split it into two columns to house our elements.",
- "Create two div
elements within your row, both with the class col-xs-6
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " div class=\"col-xs-6\"
elements within your div class=\"row\"
element.');",
- "assert(code.match(/<\\/div>/g) && code.match(/div
dentro de tu fila, ambos con la clase col-xs-6
."
- ]
- },
- "fr": {
- "title": "Séparer une rangée Bootstrap",
- "description": [
- "Maintenant que nous avons une rangée Bootstrap, séparons la en deux colonnes pour placer nos éléments.",
- "Créez deux éléments div
dans votre rangée, chacun ayant la classe col-xs-6
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908848",
- "title": "Create Bootstrap Wells",
- "description": [
- "Bootstrap has a class called well
that can create a visual sense of depth for your columns.",
- "Nest one div
element with the class well
within each of your col-xs-6
div
elements."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " div
element with the class well
inside each of your div
elements with the class \"col-xs-6\"
');",
- "assert($(\"div.row > div.col-xs-6\").length > 1, 'message: Nest both of your div
elements with the class \"col-xs-6\"
within your div
element with the class \"row\"
.');",
- "assert(code.match(/<\\/div>/g) && code.match(/well
que crea una sensación visual de profundidad para tus columnas.",
- "Anida un elemento div
con la clase well
dentro de cada uno de tus elementos div
que tienen la clase col-xs-6
."
- ]
- },
- "fr": {
- "title": "Créez un \"puit\" (well) Bootstrap",
- "description": [
- "Bootstrap possède une classe appelée well
qui peux créer une certaine profondeur pour vos colonnes.",
- "Nichez un élément div
avec la classe well
dans chacun de vos éléments col-xs-6
div
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908849",
- "title": "Add Elements within Your Bootstrap Wells",
- "description": [
- "Now we're several div
elements deep on each column of our row. This is as deep as we'll need to go. Now we can add our button
elements.",
- "Nest three button
elements within each of your well
div
elements."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " button
elements within each of your div
elements with class well
.');",
- "assert($(\"button\") && $(\"button\").length > 5, 'message: You should have a total of 6 button
elements.');",
- "assert(code.match(/<\\/button>/g) && code.match(/div
dentro de cada columna de nuestra fila. No iremos más profundo que esto. Ahora podemos agregar nuestros elementos button
.",
- "Anida tres elementos button
dentro de cada uno de tus elementos div
que tienen la clase well
."
- ]
- },
- "fr": {
- "title": "Ajouter des éléments dans un puit Bootstrap",
- "description": [
- "Nous avons maintenant plusieurs niveaux de profondeur d'éléments div
dans chaque colonne de notre rangée. Ceci est suffisant pour le moment. Maintenant nous pouvons ajouter nos éléments button
.",
- "Nichez trois éléments button
dans chaque élément well
div
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908850",
- "title": "Apply the Default Bootstrap Button Style",
- "description": [
- "Bootstrap has another button class called btn-default
.",
- "Apply both the btn
and btn-default
classes to each of your button
elements."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " btn
class to each of your button
elements.');",
- "assert($(\".btn-default\").length > 5, 'message: Apply the btn-default
class to each of your button
elements.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Aplica el estilo de botón predeterminado de Bootstrap",
- "description": [
- "Bootstrap tiene otra clase de botón llamada btn-default
.",
- "Aplica las clases btn
y btn-default
a cada uno de tus elementos button
."
- ]
- },
- "fr": {
- "title": "Appliquer le style de bouton par défaut de Bootstrap",
- "description": [
- "Bootstrap possède une autre classe de bouton appelée btn-default
.",
- "Appliquez les deux classes btn
et btn-default
à chacun de vos éléments button
"
- ]
- }
- },
- "guideUrl": "https://guide.freecodecamp.org/certificates/apply-the-default-bootstrap-button-style"
- },
- {
- "id": "bad87fee1348bd9aec908852",
- "title": "Create a Class to Target with jQuery Selectors",
- "description": [
- "Not every class needs to have corresponding CSS. Sometimes we create classes just for the purpose of selecting these elements more easily using jQuery.",
- "Give each of your button
elements the class target
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " target
class to each of your button
elements.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Crea una clase para usar con selectores de jQuery",
- "description": [
- "No todas las clases necesitan tener un código CSS correspondiente. A veces creamos clases sólo con el propósito de seleccionar esos elementos más fácilmente usando jQuery.",
- "Dale a cada uno de tus elementos button
la clase target
."
- ]
- },
- "fr": {
- "title": "Créez une classe à cibler avec les sélécteurs jQuery",
- "description": [
- "Toutes les classes ne nécéssitent pas d'avoir un code CSS qui leur correspondent. Parfois ous créons des classes dans le seul but de pouvoir sélectionner ces éléments plus facilement en utilisant jQuery.",
- "Donnez à chacun de vos éléments button
la classe target
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908853",
- "title": "Add id Attributes to Bootstrap Elements",
- "description": [
- "Recall that in addition to class attributes, you can give each of your elements an id
attribute.",
- "Each id must be unique to a specific element and used only once per page.",
- "Let's give a unique id to each of our div
elements of class well
.",
- "Remember that you can give an element an id like this:",
- "<div class=\"well\" id=\"center-well\">
",
- "Give the well on the left the id of left-well
. Give the well on the right the id of right-well
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " well
the id of left-well
.');",
- "assert($(\".col-xs-6\").children(\"#right-well\") && $(\".col-xs-6\").children(\"#right-well\").length > 0, 'message: Give your right well
the id of right-well
.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Asígnales atributos de identificación (id) a tus elementos de Bootstrap",
- "description": [
- "Recuerda que, además de los atributos de clase, también puedes darle a cada uno de tus elementos un atributo id
.",
- "Cada id debe ser único para un elemento específico y ser usado solamente una vez por página.",
- "Vamos a darle un id único a cada uno de nuestros elementos div
que tienen la clase well
.",
- "Recuerda que puedes darle a un elemento un id como el siguiente:",
- "<div class=\"well\" id=\"center-well\">
",
- "Dale al pozo de la izquireda el id left-well
. Al pozo de la derecha, dale un id right-well
."
- ]
- },
- "fr": {
- "title": "Ajouter des attributs ID à vos éléments Bootstrap",
- "description": [
- "Rappelez vous qu'en plus des attributs classes, vous pouvez donnez à chacun de vos éléments un attribut id
.",
- "Chaque id doit être unique pour un élément donné et utilisé une seule fois par page.",
- "Donnons un id unique à chacun de nos éléments div
de classe well
.",
- "Rappelez vous que vous pouvez donner un id à un élément ainsi :",
- "<div class=\"well\" id=\"center-well\">
",
- "Donnez au puit sur la gauche un id de left-well
. Donnez au puit sur la droite un id de right-well
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908854",
- "title": "Label Bootstrap Wells",
- "description": [
- "For the sake of clarity, let's label both of our wells with their ids.",
- "Above your left-well, inside its col-xs-6
div
element, add a h4
element with the text #left-well
.",
- "Above your right-well, inside its col-xs-6
div
element, add a h4
element with the text #right-well
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " h4
element to each of your <div class=\"col-xs-6\">
elements.');",
- "assert(new RegExp(\"#left-well\",\"gi\").test($(\"h4\").text()), 'message: One h4
element should have the text #left-well
.');",
- "assert(new RegExp(\"#right-well\",\"gi\").test($(\"h4\").text()), 'message: One h4
element should have the text #right-well
.');",
- "assert(code.match(/<\\/h4>/g) && code.match(//g).length === code.match(/
h4 elements have closing tags.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Etiqueta tus pozos de Bootstrap",
- "description": [
- "Para que todo esté más claro, vamos a ponerle a todos nuestros pozos una etiqueta que sea igual a su id.",
- "Sobre tu pozo de la izquierda, dentro de su elemento
div
que tiene la clase col-xs-6
, agrega un elemento h4
con el texto #left-well
.",
- "Ahora, sobre tu pozo de la derecha, dentro de su elemento div
que tiene la clase col-xs-6
, agrega un elemento h4
con el texto #right-well
."
- ]
- },
- "fr": {
- "title": "Donner un nom aux puits Bootstrap",
- "description": [
- "Au nom de la clarté, donnons un nom à nos deux puits en accord avec leur ids",
- "Au dessus de votre puit de gauche, à l'intérieur de ses éléments col-xs-6
div
, ajoutez un élément h4
ayant le texte #left-well
.",
- "Au dessus de votre puit de droite, à l'intérieur de ses éléments col-xs-6
div
, ajoutez un élément h4
ayant le texte #right-well
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908855",
- "title": "Give Each Element a Unique id",
- "description": [
- "We will also want to be able to use jQuery to target each button by its unique id.",
- "Give each of your buttons a unique id, starting with target1
and ending with target6
.",
- "Make sure that target1
to target3
are in #left-well
, and target4
to target6
are in #right-well
."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " #left-well
",
- " #right-well
",
- " button
element should have the id target1
.');",
- "assert($(\"#left-well\").children(\"#target2\") && $(\"#left-well\").children(\"#target2\").length > 0, 'message: One button
element should have the id target2
.');",
- "assert($(\"#left-well\").children(\"#target3\") && $(\"#left-well\").children(\"#target3\").length > 0, 'message: One button
element should have the id target3
.');",
- "assert($(\"#right-well\").children(\"#target4\") && $(\"#right-well\").children(\"#target4\").length > 0, 'message: One button
element should have the id target4
.');",
- "assert($(\"#right-well\").children(\"#target5\") && $(\"#right-well\").children(\"#target5\").length > 0, 'message: One button
element should have the id target5
.');",
- "assert($(\"#right-well\").children(\"#target6\") && $(\"#right-well\").children(\"#target6\").length > 0, 'message: One button
element should have the id target6
.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Dale a cada elemento un ID único",
- "description": [
- "También quisiéramos referirnos a cada botón por su id utilizando jQuery.",
- "Dale a cada uno de tus botones un id único, comenzando con target1
y terminando con target6
.",
- "Asegúrate que target1
a target3
queden en #left-well
, mientras que target4
a target6
queden en #right-well
."
- ]
- },
- "fr": {
- "title": "Donner à chaque élément un ID unique",
- "description": [
- "Nous désirerons aussi pouvoir être capable d'utiliser jQuery pour cibler chaque bouton suivant son id unique.",
- "Donnez à chaque bouton un id unique, commençant par target1
et finissant par target6
.",
- "Assurez vous que target1
à target3
sont dans le #left-well
, et que target4
à target6
sont dans le #right-well
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908856",
- "title": "Label Bootstrap Buttons",
- "description": [
- "Just like we labeled our wells, we want to label our buttons.",
- "Give each of your button
elements text that corresponds to its id
's selector."
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " #left-well
",
- " #right-well
",
- " button
element with the id target1
the text #target1
.');",
- "assert(new RegExp(\"#target2\",\"gi\").test($(\"#target2\").text()), 'message: Give your button
element with the id target2
the text #target2
.');",
- "assert(new RegExp(\"#target3\",\"gi\").test($(\"#target3\").text()), 'message: Give your button
element with the id target3
the text #target3
.');",
- "assert(new RegExp(\"#target4\",\"gi\").test($(\"#target4\").text()), 'message: Give your button
element with the id target4
the text #target4
.');",
- "assert(new RegExp(\"#target5\",\"gi\").test($(\"#target5\").text()), 'message: Give your button
element with the id target5
the text #target5
.');",
- "assert(new RegExp(\"#target6\",\"gi\").test($(\"#target6\").text()), 'message: Give your button
element with the id target6
the text #target6
.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Etiqueta los botones con Bootstrap",
- "description": [
- "De la misma forma en que etiquetamos nuestros pozos, ahora vamos a etiquetar nuestros botones.",
- "Dale a cada uno de tus elementos button
un texto que corresponda con su id
."
- ]
- },
- "fr": {
- "title": "Donnez un nom à vos boutons Bootstrap",
- "description": [
- "De la même façon que nous avons donné un nom à nos puits, nous voulons nommer nos boutons.",
- "Donnez à chaque élément button
un texte qui corresponde à son id
."
- ]
- }
- }
- },
- {
- "id": "bad87fee1348bd9aec908857",
- "title": "Use Comments to Clarify Code",
- "description": [
- "When we start using jQuery, we will modify HTML elements without needing to actually change them in HTML.",
- "Let's make sure that everyone knows they shouldn't actually modify any of this code directly.",
- "Remember that you can start a comment with <!--
and end a comment with -->
",
- "Add a comment at the top of your HTML that says Only change code above this line.
"
- ],
- "challengeSeed": [
- "jQuery Playground
",
- " #left-well
",
- " #right-well
",
- " Only change code above this line
.');",
- "assert(code.match(/-->.*\\n+.+/g), 'message: Be sure to close your comment with -->
.');",
- "assert(code.match(//g).length, 'message: You should have the same number of comment openers and closers.');"
- ],
- "type": "waypoint",
- "challengeType": 0,
- "translations": {
- "es": {
- "title": "Usa elementos para explicar tu código",
- "description": [
- "Cuando comencemos a usar jQuery, modificarmemos los elementos HTML sin necesidad de hacer cambios reales en el código HTML.",
- "Vamos a asegurar que cualquier persona sepa que no debe modificar nada en este código directamente.",
- "Recuerda que puedes iniciar un comentario usando <!--
y terminarlo usando -->
",
- "Agrega un comentario al inicio de tu código HTML que diga Only change code above this line.
"
- ]
- },
- "fr": {
- "title": "Utiliser des commentaires pour clarifier son code",
- "description": [
- "Quand nous commencerons à utiliser jQuery, nous modifierons les éléments HTML sans avoir besoin de les changer directement dans le fichier HTML.",
- "Assurons nous que tout le monde sache qu'ils ne devraient pas modifier quoi que ce soit dans le code HTML.",
- "Rappelez vous que vous pouvez commencer un commentaire avec <!--
et le finir avec -->
",
- "Ajoutez un commentaire en haut de l'HTML qui annonce Only change code above this line.
(Changez seulement le code au dessus de cette ligne.)"
- ]
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json b/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json
deleted file mode 100644
index 7b524b22f5..0000000000
--- a/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json
+++ /dev/null
@@ -1,124 +0,0 @@
-{
- "name": "Front End Libraries Projects",
- "order": 8,
- "time": "150 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "bd7158d8c442eddfaeb5bd13",
- "title": "Build a Random Quote Machine",
- "description": [
- "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.",
- "Here's a working example. Try not to look at its code.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
- ],
- "tests": [],
- "type": "zipline",
- "isRequired": true,
- "challengeType": 3,
- "translations": {
- "es": {
- "title": "Crea una máquina de frases aleatorias"
- },
- "ru": {
- "title": "Создайте генератор случайных цитат"
- }
- }
- },
- {
- "id": "bd7157d8c242eddfaeb5bd13",
- "title": "Build a Markdown Previewer",
- "description": [
- "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.",
- "Here's a working example. Try not to look at its code.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
- ],
- "releasedOn": "January 10, 2017",
- "tests": [],
- "type": "zipline",
- "isRequired": true,
- "challengeType": 3,
- "translations": {
- "es": {
- "title": "Crea una caja de recetas"
- },
- "ru": {
- "title": "Создайте хранилище рецептов"
- }
- }
- },
- {
- "id": "587d7dbc367417b2b2512bae",
- "title": "Build a Drum Machine",
- "description": [
- "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.",
- "Here's a working example. Try not to look at its code.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
- ],
- "releasedOn": "February 17, 2017",
- "tests": [],
- "type": "zipline",
- "isRequired": true,
- "challengeType": 3,
- "translations": {
- "es": {
- "title": "Crea un Juego de la vida"
- },
- "ru": {
- "title": "Создайте игру \"Жизнь\""
- }
- }
- },
- {
- "id": "bd7158d8c442eddfaeb5bd17",
- "title": "Build a JavaScript Calculator",
- "description": [
- "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.",
- "Here's a working example. Try not to look at its code.",
- "Note On Calculator Logic: It should be noted that there are two main schools of thought on calculator input logic: immediate execution logic and formula logic. Our example utilizes formula logic and observes order of operation precedence, immediate execution does not. Either is acceptable, but please note that depending on which you choose, your calculator may yield different results than ours for certain equations (see below example). As long as your math can be verified by another production calculator, please do not consider this a bug.",
- "EXAMPLE: 3 + 5 x 6 - 2 / 4 =
",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: 11.5
32.5
https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
- ],
- "tests": [],
- "type": "zipline",
- "challengeType": 3,
- "isRequired": true,
- "translations": {
- "es": {
- "title": "Crea una calculadora JavaScript"
- }
- }
- },
- {
- "id": "bd7158d8c442eddfaeb5bd0f",
- "title": "Build a Pomodoro Clock",
- "description": [
- "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.",
- "Here's a working example. Try not to look at its code.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
- ],
- "tests": [],
- "type": "zipline",
- "isRequired": true,
- "challengeType": 3,
- "translations": {
- "es": {
- "title": "Crea un reloj pomodoro"
- },
- "ru": {
- "title": "Создайте таймер Pomodoro"
- }
- }
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/03-front-end-libraries/jquery.json b/packages/learn/seed/tmp/03-front-end-libraries/jquery.json
deleted file mode 100644
index 7e0018d9b2..0000000000
--- a/packages/learn/seed/tmp/03-front-end-libraries/jquery.json
+++ /dev/null
@@ -1,1549 +0,0 @@
-{
- "name": "jQuery",
- "order": 3,
- "time": "3 hours",
- "helpRoom": "Help",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css"
- }
- ],
- "challenges": [
- {
- "id": "5a61d23e84acdd9e42575aa3",
- "title": "Introduction to jQuery",
- "description": [
- "",
- "",
- "jQuery is one of the many libraries for JavaScript. It is designed to simplify scripting done on the client side.",
- "",
- "@@STEP@@",
- "",
- "",
- "jQuery's most recognizable characteristic is its dollar sign ($
) syntax. With it, you can easily manipulate elements, create animations and handle input events.",
- "",
- "@@STEP@@"
- ],
- "releasedOn": "",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false,
- "translations": {}
- },
- {
- "id": "bad87fee1348bd9acdd08826",
- "title": "Learn How Script Tags and Document Ready Work",
- "description": [
- "Now we're ready to learn jQuery, the most popular JavaScript tool of all time.",
- "Before we can start using jQuery, we need to add some things to our HTML.",
- "First, add a script
element at the top of your page. Be sure to close it on the following line.",
- "Your browser will run any JavaScript inside a script
element, including jQuery.",
- "Inside your script
element, add this code: $(document).ready(function() {
to your script
. Then close it on the following line (still inside your script
element) with: });
",
- "We'll learn more about functions
later. The important thing to know is that code you put inside this function
will run as soon as your browser has loaded your page.",
- "This is important because without your document ready function
, your code may run before your HTML is rendered, which would cause bugs."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "",
- "jQuery Playground
",
- " #left-well
",
- " #right-well
",
- "
text
element should have a label of 12 and a y
value of 61.');",
- "assert($('text').eq(1).text() == '31' && $('text').eq(1).attr('y') == '4', 'message: The second text
element should have a label of 31 and a y
value of 4.');",
- "assert($('text').eq(2).text() == '22' && $('text').eq(2).attr('y') == '31', 'message: The third text
element should have a label of 22 and a y
value of 31.');",
- "assert($('text').eq(3).text() == '17' && $('text').eq(3).attr('y') == '46', 'message: The fourth text
element should have a label of 17 and a y
value of 46.');",
- "assert($('text').eq(4).text() == '25' && $('text').eq(4).attr('y') == '22', 'message: The fifth text
element should have a label of 25 and a y
value of 22.');",
- "assert($('text').eq(5).text() == '18' && $('text').eq(5).attr('y') == '43', 'message: The sixth text
element should have a label of 18 and a y
value of 43.');",
- "assert($('text').eq(6).text() == '29' && $('text').eq(6).attr('y') == '10', 'message: The seventh text
element should have a label of 29 and a y
value of 10.');",
- "assert($('text').eq(7).text() == '14' && $('text').eq(7).attr('y') == '55', 'message: The eighth text
element should have a label of 14 and a y
value of 55.');",
- "assert($('text').eq(8).text() == '9' && $('text').eq(8).attr('y') == '70', 'message: The ninth text
element should have a label of 9 and a y
value of 70.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7faa367417b2b2512bd3",
- "title": "Style D3 Labels",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "D3 methods can add styles to the bar labels. The fill
attribute sets the color of the text for a text
node. The style()
method sets CSS rules for other styles, such as \"font-family\" or \"font-size\".",
- "font-size
of the text
elements to 25px, and the color of the text to red."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('text').css('fill') == 'rgb(255, 0, 0)', 'message: The labels should all have a fill
color of red.');",
- "assert($('text').css('font-size') == '25px', 'message: The labels should all have a font-size
of 25 pixels.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7faa367417b2b2512bd4",
- "title": "Add a Hover Effect to a D3 Element",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "It's possible to add effects that highlight a bar when the user hovers over it with the mouse. So far, the styling for the rectangles is applied with the built-in D3 and SVG methods, but you can use CSS as well.",
- "You set the CSS class on the SVG elements with the attr()
method. Then the :hover
pseudo-class for your new class holds the style rules for any hover effects.",
- "attr()
method to add a class of bar
to all the rect
elements. This changes the fill
color of the bar to brown when you mouse over it."
- ],
- "challengeSeed": [
- "",
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('rect').attr('class') == \"bar\", 'message: Your rect
elements should have a class of bar
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7faa367417b2b2512bd6",
- "title": "Add a Tooltip to a D3 Element",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "A tooltip shows more information about an item on a page when the user hovers over that item. There are several ways to add a tooltip to a visualization, this challenge uses the SVG title
element.",
- "title
pairs with the text()
method to dynamically add data to the bars.",
- "title
element under each rect
node. Then call the text()
method with a callback function so the text displays the data value."
- ],
- "challengeSeed": [
- "",
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('title').length == 9, 'message: Your code should have 9 title
elements.');",
- "assert($('title').eq(0).text() == '12', 'message: The first title
element should have tooltip text of 12.');",
- "assert($('title').eq(1).text() == '31', 'message: The second title
element should have tooltip text of 31.');",
- "assert($('title').eq(2).text() == '22', 'message: The third title
element should have tooltip text of 22.');",
- "assert($('title').eq(3).text() == '17', 'message: The fourth title
element should have tooltip text of 17.');",
- "assert($('title').eq(4).text() == '25', 'message: The fifth title
element should have tooltip text of 25.');",
- "assert($('title').eq(5).text() == '18', 'message: The sixth title
element should have tooltip text of 18.');",
- "assert($('title').eq(6).text() == '29', 'message: The seventh title
element should have tooltip text of 29.');",
- "assert($('title').eq(7).text() == '14', 'message: The eighth title
element should have tooltip text of 14.');",
- "assert($('title').eq(8).text() == '9', 'message: The ninth title
element should have tooltip text of 9.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fab367417b2b2512bd7",
- "title": "Create a Scatterplot with SVG Circles",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "A scatter plot is another type of visualization. It usually uses circles to map data points, which have two values each. These values tie to the x
and y
axes, and are used to position the circle in the visualization.",
- "SVG has a circle
tag to create the circle shape. It works a lot like the rect
elements you used for the bar chart.",
- "data()
, enter()
, and append()
methods to bind dataset
to new circle
elements that are appended to the SVG canvas."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('circle').length == 10, 'message: Your code should have 10 circle
elements.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fab367417b2b2512bd8",
- "title": "Add Attributes to the Circle Elements",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "The last challenge created the circle
elements for each point in the dataset
, and appended them to the SVG canvas. But D3 needs more information about the position and size of each circle
to display them correctly.",
- "A circle
in SVG has three main attributes. The cx
and cy
attributes are the coordinates. They tell D3 where to position the center of the shape on the SVG canvas. The radius (r
attribute) gives the size of the circle
.",
- "Just like the rect
y
coordinate, the cy
attribute for a circle
is measured from the top of the SVG canvas, not from the bottom.",
- "All three attributes can use a callback function to set their values dynamically. Remember that all methods chained after data(dataset)
run once per item in dataset
. The d
parameter in the callback function refers to the current item in dataset
, which is an array for each point. You use bracket notation, like d[0]
, to access the values in that array.",
- "cx
, cy
, and r
attributes to the circle
elements. The cx
value should be the first number in the array for each item in dataset
. The cy
value should be based off the second number in the array, but make sure to show the chart right-side-up and not inverted. The r
value should be 5 for all circles."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('circle').length == 10, 'message: Your code should have 10 circle
elements.');",
- "assert($('circle').eq(0).attr('cx') == '34' && $('circle').eq(0).attr('cy') == '422' && $('circle').eq(0).attr('r') == '5', 'message: The first circle
element should have a cx
value of 34, a cy
value of 422, and an r
value of 5.');",
- "assert($('circle').eq(1).attr('cx') == '109' && $('circle').eq(1).attr('cy') == '220' && $('circle').eq(1).attr('r') == '5', 'message: The second circle
element should have a cx
value of 109, a cy
value of 220, and an r
value of 5.');",
- "assert($('circle').eq(2).attr('cx') == '310' && $('circle').eq(2).attr('cy') == '380' && $('circle').eq(2).attr('r') == '5', 'message: The third circle
element should have a cx
value of 310, a cy
value of 380, and an r
value of 5.');",
- "assert($('circle').eq(3).attr('cx') == '79' && $('circle').eq(3).attr('cy') == '89' && $('circle').eq(3).attr('r') == '5', 'message: The fourth circle
element should have a cx
value of 79, a cy
value of 89, and an r
value of 5.');",
- "assert($('circle').eq(4).attr('cx') == '420' && $('circle').eq(4).attr('cy') == '280' && $('circle').eq(4).attr('r') == '5', 'message: The fifth circle
element should have a cx
value of 420, a cy
value of 280, and an r
value of 5.');",
- "assert($('circle').eq(5).attr('cx') == '233' && $('circle').eq(5).attr('cy') == '355' && $('circle').eq(5).attr('r') == '5', 'message: The sixth circle
element should have a cx
value of 233, a cy
value of 355, and an r
value of 5.');",
- "assert($('circle').eq(6).attr('cx') == '333' && $('circle').eq(6).attr('cy') == '404' && $('circle').eq(6).attr('r') == '5', 'message: The seventh circle
element should have a cx
value of 333, a cy
value of 404, and an r
value of 5.');",
- "assert($('circle').eq(7).attr('cx') == '222' && $('circle').eq(7).attr('cy') == '167' && $('circle').eq(7).attr('r') == '5', 'message: The eighth circle
element should have a cx
value of 222, a cy
value of 167, and an r
value of 5.');",
- "assert($('circle').eq(8).attr('cx') == '78' && $('circle').eq(8).attr('cy') == '180' && $('circle').eq(8).attr('r') == '5', 'message: The ninth circle
element should have a cx
value of 78, a cy
value of 180, and an r
value of 5.');",
- "assert($('circle').eq(9).attr('cx') == '21' && $('circle').eq(9).attr('cy') == '377' && $('circle').eq(9).attr('r') == '5', 'message: The tenth circle
element should have a cx
value of 21, a cy
value of 377, and an r
value of 5.');"
- ],
- "solutions": [],
- "hints": [
- "The cy attribute should be the second number of the data point array subtracted from the height of the SVG."
- ],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fab367417b2b2512bd9",
- "title": "Add Labels to Scatter Plot Circles",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "You can add text to create labels for the points in a scatter plot.",
- "The goal is to display the comma-separated values for the first (x
) and second (y
) fields of each item in dataset
.",
- "The text
nodes need x
and y
attributes to position it on the SVG canvas. In this challenge, the y
value (which determines height) can use the same value that the circle
uses for its cy
attribute. The x
value can be slightly larger than the cx
value of the circle
, so the label is visible. This will push the label to the right of the plotted point.",
- "text
elements. The text of the label should be the two values separated by a comma and a space. For example, the label for the first point is \"34, 78\". Set the x
attribute so it's 5 units more than the value you used for the cx
attribute on the circle
. Set the y
attribute the same way that's used for the cy
value on the circle
."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('text').length == 10, 'message: Your code should have 10 text
elements.');",
- "assert($('text').eq(0).text() == '34, 78' && $('text').eq(0).attr('x') == '39' && $('text').eq(0).attr('y') == '422', 'message: The first label should have text of \"34, 78\", an x
value of 39, and a y
value of 422.');",
- "assert($('text').eq(1).text() == '109, 280' && $('text').eq(1).attr('x') == '114' && $('text').eq(1).attr('y') == '220', 'message: The second label should have text of \"109, 280\", an x
value of 114, and a y
value of 220.');",
- "assert($('text').eq(2).text() == '310, 120' && $('text').eq(2).attr('x') == '315' && $('text').eq(2).attr('y') == '380', 'message: The third label should have text of \"310, 120\", an x
value of 315, and a y
value of 380.');",
- "assert($('text').eq(3).text() == '79, 411' && $('text').eq(3).attr('x') == '84' && $('text').eq(3).attr('y') == '89', 'message: The fourth label should have text of \"79, 411\", an x
value of 84, and a y
value of 89.');",
- "assert($('text').eq(4).text() == '420, 220' && $('text').eq(4).attr('x') == '425' && $('text').eq(4).attr('y') == '280', 'message: The fifth label should have text of \"420, 220\", an x
value of 425, and a y
value of 280.');",
- "assert($('text').eq(5).text() == '233, 145' && $('text').eq(5).attr('x') == '238' && $('text').eq(5).attr('y') == '355', 'message: The sixth label should have text of \"233, 145\", an x
value of 238, and a y
value of 355.');",
- "assert($('text').eq(6).text() == '333, 96' && $('text').eq(6).attr('x') == '338' && $('text').eq(6).attr('y') == '404', 'message: The seventh label should have text of \"333, 96\", an x
value of 338, and a y
value of 404.');",
- "assert($('text').eq(7).text() == '222, 333' && $('text').eq(7).attr('x') == '227' && $('text').eq(7).attr('y') == '167', 'message: The eighth label should have text of \"222, 333\", an x
value of 227, and a y
value of 167.');",
- "assert($('text').eq(8).text() == '78, 320' && $('text').eq(8).attr('x') == '83' && $('text').eq(8).attr('y') == '180', 'message: The ninth label should have text of \"78, 320\", an x
value of 83, and a y
value of 180.');",
- "assert($('text').eq(9).text() == '21, 123' && $('text').eq(9).attr('x') == '26' && $('text').eq(9).attr('y') == '377', 'message: The tenth label should have text of \"21, 123\", an x
value of 26, and a y
value of 377.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fab367417b2b2512bda",
- "title": "Create a Linear Scale with D3",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "The bar and scatter plot charts both plotted data directly onto the SVG canvas. However, if the height of a bar or one of the data points were larger than the SVG height or width values, it would go outside the SVG area.",
- "In D3, there are scales to help plot data. Scales
are functions that tell the program how to map a set of raw data points onto the pixels of the SVG canvas.",
- "For example, say you have a 100x500-sized SVG canvas and you want to plot Gross Domestic Product (GDP) for a number of countries. The set of numbers would be in the billion or trillion-dollar range. You provide D3 a type of scale to tell it how to place the large GDP values into that 100x500-sized area.",
- "It's unlikely you would plot raw data as-is. Before plotting it, you set the scale for your entire data set, so that the x
and y
values fit your canvas width and height.",
- "D3 has several scale types. For a linear scale (usually used with quantitative data), there is the D3 method scaleLinear()
:",
- " const scale = d3.scaleLinear()
",
- "By default, a scale uses the identity relationship. The value of the input is the same as the value of the output. A separate challenge covers how to change this.",
- "scale
variable to create a linear scale. Then set the output
variable to the scale called with an input argument of 50."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('h2').text() == '50', 'message: The text in the h2
should be 50.');",
- "assert(code.match(/\\.scaleLinear/g), 'message: Your code should use the scaleLinear()
method.');",
- "assert(output == 50 && code.match(/scale\\(\\s*?50\\s*?\\)/g), 'message: The output
variable should call scale
with an argument of 50.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fac367417b2b2512bdb",
- "title": "Set a Domain and a Range on a Scale",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "By default, scales use the identity relationship - the input value maps to the output value. But scales can be much more flexible and interesting.",
- "Say a data set has values ranging from 50 to 480. This is the input information for a scale, and is also known as the domain.",
- "You want to map those points along the x
axis on the SVG canvas, between 10 units and 500 units. This is the output information, which is also known as the range.",
- "The domain()
and range()
methods set these values for the scale. Both methods take an array of at least two elements as an argument. Here's an example:",
- "// Set a domain", - "Notice that the scale uses the linear relationship between the domain and range values to figure out what the output should be for a given number. The minimum value in the domain (50) maps to the minimum value (10) in the range.", - "
// The domain covers the set of input values
scale.domain([50, 480]);
// Set a range
// The range covers the set of output values
scale.range([10, 500]);
scale(50) // Returns 10
scale(480) // Returns 500
scale(325) // Returns 323.37
scale(750) // Returns 807.67
d3.scaleLinear()
[250, 500]
and range to [10, 150]
.",
- "Notedomain()
and range()
methods onto the scale
variable."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert(code.match(/\\.domain/g), 'message: Your code should use the domain()
method.');",
- "assert(JSON.stringify(scale.domain()) == JSON.stringify([250, 500]), 'message: The domain()
of the scale should be set to [250, 500]
.');",
- "assert(code.match(/\\.range/g), 'message: Your code should use the range()
method.');",
- "assert(JSON.stringify(scale.range()) == JSON.stringify([10, 150]), 'message: The range()
of the scale should be set to [10, 150]
.');",
- "assert($('h2').text() == '-102', 'message: The text in the h2
should be -102.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fac367417b2b2512bdc",
- "title": "Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "The D3 methods domain()
and range()
set that information for your scale based on the data. There are a couple methods to make that easier.",
- "Often when you set the domain, you'll want to use the minimum and maximum values within the data set. Trying to find these values manually, especially in a large data set, may cause errors.",
- "D3 has two methods - min()
and max()
to return this information. Here's an example:",
- "const exampleData = [34, 234, 73, 90, 6, 52];", - "A dataset may have nested arrays, like the [x, y] coordinate pairs that were in the scatter plot example. In that case, you need to tell D3 how to calculate the maximum and minimum.", - "Fortunately, both the
d3.min(exampleData) // Returns 6
d3.max(exampleData) // Returns 234
min()
and max()
methods take a callback function.",
- "In this example, the callback function's argument d
is for the current inner array. The callback needs to return the element from the inner array (the x or y value) over which you want to compute the maximum or minimum. Here's an example for how to find the min and max values with an array of arrays:",
- "const locationData = [[1, 7],[6, 3],[8, 3]];", - "
// Returns the smallest number out of the first elements
const minX = d3.min(locationData, (d) => d[0]);
// minX compared 1, 6, and 8 and is set to 1
positionData
variable holds a 3-dimensional (3D) array. Use a D3 method to find the maximum value of the z coordinate (the third value) from the arrays and save it in the output
variable.",
- "Noteh2
should be 8.');",
- "assert(code.match(/\\.max/g), 'message: Your code should use the max()
method.')"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fac367417b2b2512bdd",
- "title": "Use Dynamic Scales",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "The D3 min()
and max()
methods are useful to help set the scale.",
- "Given a complex data set, one priority is to set the scale so the visualization fits the SVG container's width and height. You want all the data plotted inside the SVG canvas so it's visible on the web page.",
- "The example below sets the x-axis scale for scatter plot data. The domain()
method passes information to the scale about the raw data values for the plot. The range()
method gives it information about the actual space on the web page for the visualization.",
- "In the example, the domain goes from 0 to the maximum in the set. It uses the max()
method with a callback function based on the x values in the arrays. The range uses the SVG canvas' width (w
), but it includes some padding, too. This puts space between the scatter plot dots and the edge of the SVG canvas.",
- "const dataset = [", - "The padding may be confusing at first. Picture the x-axis as a horizontal line from 0 to 500 (the width value for the SVG canvas). Including the padding in the
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
// Padding between the SVG canvas boundary and the plot
const padding = 30;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
range()
method forces the plot to start at 30 along that line (instead of 0), and end at 470 (instead of 500).",
- "yScale
variable to create a linear y-axis scale. The domain should start at zero and go to the maximum y value in the set. The range should use the SVG height (h
) and include padding.",
- "Noteh2
should be 30.');",
- "assert(JSON.stringify(yScale.domain()) == JSON.stringify([0, 411]), 'message: The domain()
of yScale should be equivalent to [0, 411]
.');",
- "assert(JSON.stringify(yScale.range()) == JSON.stringify([470, 30]), 'message: The range()
of yScale should be equivalent to [470, 30]
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fac367417b2b2512bde",
- "title": "Use a Pre-Defined Scale to Place Elements",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "With the scales set up, it's time to map the scatter plot again. The scales are like processing functions that turn the x and y raw data into values that fit and render correctly on the SVG canvas. They keep the data within the screen's plotting area.",
- "You set the coordinate attribute values for an SVG shape with the scaling function. This includes x
and y
attributes for rect
or text
elements, or cx
and cy
for circles
. Here's an example:",
- "shape", - "Scales set shape coordinate attributes to place the data points onto the SVG canvas. You don't need to apply scales when you display the actual data value, for example, in the
.attr(\"x\", (d) => xScale(d[0]))
text()
method for a tooltip or label.",
- "xScale
and yScale
to position both the circle
and text
shapes onto the SVG canvas. For the circles
, apply the scales to set the cx
and cy
attributes. Give them a radius of 5 units, too.",
- "For the text
elements, apply the scales to set the x
and y
attributes. The labels should be offset to the right of the dots. To do this, add 10 units to the x data value before passing it to the xScale
."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert($('circle').length == 10, 'message: Your code should have 10 circle
elements.');",
- "assert(Math.round($('circle').eq(0).attr('cx')) == '91' && Math.round($('circle').eq(0).attr('cy')) == '368' && $('circle').eq(0).attr('r') == '5', 'message: The first circle
element should have a cx
value of approximately 91 and a cy
value of approximately 368 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(1).attr('cx')) == '159' && Math.round($('circle').eq(1).attr('cy')) == '181' && $('circle').eq(1).attr('r') == '5', 'message: The second circle
element should have a cx
value of approximately 159 and a cy
value of approximately 181 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(2).attr('cx')) == '340' && Math.round($('circle').eq(2).attr('cy')) == '329' && $('circle').eq(2).attr('r') == '5', 'message: The third circle
element should have a cx
value of approximately 340 and a cy
value of approximately 329 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(3).attr('cx')) == '131' && Math.round($('circle').eq(3).attr('cy')) == '60' && $('circle').eq(3).attr('r') == '5', 'message: The fourth circle
element should have a cx
value of approximately 131 and a cy
value of approximately 60 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(4).attr('cx')) == '440' && Math.round($('circle').eq(4).attr('cy')) == '237' && $('circle').eq(4).attr('r') == '5', 'message: The fifth circle
element should have a cx
value of approximately 440 and a cy
value of approximately 237 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(5).attr('cx')) == '271' && Math.round($('circle').eq(5).attr('cy')) == '306' && $('circle').eq(5).attr('r') == '5', 'message: The sixth circle
element should have a cx
value of approximately 271 and a cy
value of approximately 306 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(6).attr('cx')) == '361' && Math.round($('circle').eq(6).attr('cy')) == '351' && $('circle').eq(6).attr('r') == '5', 'message: The seventh circle
element should have a cx
value of approximately 361 and a cy
value of approximately 351 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(7).attr('cx')) == '261' && Math.round($('circle').eq(7).attr('cy')) == '132' && $('circle').eq(7).attr('r') == '5', 'message: The eighth circle
element should have a cx
value of approximately 261 and a cy
value of approximately 132 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(8).attr('cx')) == '131' && Math.round($('circle').eq(8).attr('cy')) == '144' && $('circle').eq(8).attr('r') == '5', 'message: The ninth circle
element should have a cx
value of approximately 131 and a cy
value of approximately 144 after applying the scales. It should also have an r
value of 5.');",
- "assert(Math.round($('circle').eq(9).attr('cx')) == '79' && Math.round($('circle').eq(9).attr('cy')) == '326' && $('circle').eq(9).attr('r') == '5', 'message: The tenth circle
element should have a cx
value of approximately 79 and a cy
value of approximately 326 after applying the scales. It should also have an r
value of 5.');",
- "assert($('text').length == 10, 'message: Your code should have 10 text
elements.');",
- "assert(Math.round($('text').eq(0).attr('x')) == '100' && Math.round($('text').eq(0).attr('y')) == '368', 'message: The first label should have an x
value of approximately 100 and a y
value of approximately 368 after applying the scales.');",
- "assert(Math.round($('text').eq(1).attr('x')) == '168' && Math.round($('text').eq(1).attr('y')) == '181', 'message: The second label should have an x
value of approximately 168 and a y
value of approximately 181 after applying the scales.');",
- "assert(Math.round($('text').eq(2).attr('x')) == '350' && Math.round($('text').eq(2).attr('y')) == '329', 'message: The third label should have an x
value of approximately 350 and a y
value of approximately 329 after applying the scales.');",
- "assert(Math.round($('text').eq(3).attr('x')) == '141' && Math.round($('text').eq(3).attr('y')) == '60', 'message: The fourth label should have an x
value of approximately 141 and a y
value of approximately 60 after applying the scales.');",
- "assert(Math.round($('text').eq(4).attr('x')) == '449' && Math.round($('text').eq(4).attr('y')) == '237', 'message: The fifth label should have an x
value of approximately 449 and a y
value of approximately 237 after applying the scales.');",
- "assert(Math.round($('text').eq(5).attr('x')) == '280' && Math.round($('text').eq(5).attr('y')) == '306', 'message: The sixth label should have an x
value of approximately 280 and a y
value of approximately 306 after applying the scales.');",
- "assert(Math.round($('text').eq(6).attr('x')) == '370' && Math.round($('text').eq(6).attr('y')) == '351', 'message: The seventh label should have an x
value of approximately 370 and a y
value of approximately 351 after applying the scales.');",
- "assert(Math.round($('text').eq(7).attr('x')) == '270' && Math.round($('text').eq(7).attr('y')) == '132', 'message: The eighth label should have an x
value of approximately 270 and a y
value of approximately 132 after applying the scales.');",
- "assert(Math.round($('text').eq(8).attr('x')) == '140' && Math.round($('text').eq(8).attr('y')) == '144', 'message: The ninth label should have an x
value of approximately 140 and a y
value of approximately 144 after applying the scales.');",
- "assert(Math.round($('text').eq(9).attr('x')) == '88' && Math.round($('text').eq(9).attr('y')) == '326', 'message: The tenth label should have an x
value of approximately 88 and a y
value of approximately 326 after applying the scales.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fad367417b2b2512bdf",
- "title": "Add Axes to a Visualization",
- "required": [
- {
- "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"
- }
- ],
- "description": [
- "Another way to improve the scatter plot is to add an x-axis and a y-axis.",
- "D3 has two methods axisLeft()
and axisBottom()
to render the y and x axes, respectively. (Axes is the plural form of axis). Here's an example to create the x-axis based on the xScale
in the previous challenges:",
- "const xAxis = d3.axisBottom(xScale);
",
- "The next step is to render the axis on the SVG canvas. To do so, you can use a general SVG component, the g
element. The g
stands for group.",
- "Unlike rect
, circle
, and text
, an axis is just a straight line when it's rendered. Because it is a simple shape, using g
works.",
- "The last step is to apply a transform
attribute to position the axis on the SVG canvas in the right place. Otherwise, the line would render along the border of SVG canvas and wouldn't be visible.",
- "SVG supports different types of transforms
, but positioning an axis needs translate
. When it's applied to the g
element, it moves the whole group over and down by the given amounts. Here's an example:",
- "const xAxis = d3.axisBottom(xScale);", - "The above code places the x-axis at the bottom of the SVG canvas. Then it's passed as an argument to the
svg.append(\"g\")
.attr(\"transform\", \"translate(0, \" + (h - padding) + \")\")
.call(xAxis);
call()
method.",
- "The y-axis works is the same way, except the translate
argument is in the form (x, 0). Because translate
is a string in the attr()
method above, you can use concatenation to include variable values for its arguments.",
- "yAxis
using the axisLeft()
method. Then render the axis using a g
element. Make sure to use a transform
attribute to translate the axis by the amount of padding units right, and 0 units down. Remember to call()
the axis."
- ],
- "challengeSeed": [
- "",
- " ",
- ""
- ],
- "tests": [
- "assert(code.match(/\\.axisLeft\\(yScale\\)/g), 'message: Your code should use the axisLeft()
method with yScale
passed as the argument.');",
- "assert($('g').eq(1).attr('transform').match(/translate\\(60\\s*?,\\s*?0\\)/g), 'message: The y-axis g
element should have a transform
attribute to translate the axis by (60, 0).');",
- "assert(code.match(/\\.call\\(yAxis\\)/g), 'message: Your code should call the yAxis
.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json b/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json
deleted file mode 100644
index 2dd425bd2d..0000000000
--- a/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json
+++ /dev/null
@@ -1,693 +0,0 @@
-{
- "name": "JSON APIs and AJAX",
- "order": 2,
- "time": "2 hours",
- "helpRoom": "Help",
- "required": [
- {
- "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css"
- }
- ],
- "challenges": [
- {
- "id": "587d7fad367417b2b2512be0",
- "title": "Introduction to the JSON APIs and AJAX Challenges",
- "description": [
- "",
- "",
- "Similar to how User Interfaces help people use programs, Application Programming Interfaces (APIs) help programs interact with other programs. APIs are tools that computers use to communicate with one another, in part to send and receive data. You can use API functionality in your page once you understand how to make requests and process data from it. Programmers often use AJAX technologies when working with APIs.DOMContentLoaded
. Here's the code that does this:",
- "document.addEventListener('DOMContentLoaded',function() {", - "You can implement event handlers that go inside of the
});
DOMContentLoaded
function. You can implement an onclick
event handler which triggers when the user clicks on the element with id getMessage
, by adding the following code:",
- "document.getElementById('getMessage').onclick=function(){};", - "
DOMContentLoaded
function for the element with id of getMessage
."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "
document.getElementById
method to select the getMessage
element.');",
- "assert(typeof document.getElementById('getMessage').onclick === 'function', 'message: Your code should add an onclick
event handler.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fad367417b2b2512be2",
- "title": "Change Text with click Events",
- "description": [
- "When the click event happens, you can use JavaScript to update an HTML element.",
- "For example, when a user clicks the \"Get Message\" button, it changes the text of the element with the class message
to say \"Here is the message\".",
- "This works by adding the following code within the click event:",
- "document.getElementsByClassName('message')[0].innerHTML=\"Here is the message\";
",
- "onclick
event handler to change the text inside the message
element to say \"Here is the message\"."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "
document.getElementsByClassName
method to select the element with class message
and set its innerHTML
to the given string.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fae367417b2b2512be3",
- "title": "Get JSON with the JavaScript XMLHttpRequest Method",
- "description": [
- "You can also request data from an external source. This is where APIs come into play.",
- "Remember that APIs - or Application Programming Interfaces - are tools that computers use to communicate with one another. You'll learn how to update HTML with the data we get from APIs using a technology called AJAX.",
- "Most web APIs transfer data in a format called JSON. JSON stands for JavaScript Object Notation.",
- "JSON syntax looks very similar to JavaScript object literal notation. JSON has object properties and their current values, sandwiched between a {
and a }
.",
- "These properties and their values are often referred to as \"key-value pairs\".",
- "However, JSON transmitted by APIs are sent as bytes
, and your application receives it as a string
. These can be converted into JavaScript objects, but they are not JavaScript objects by default. The JSON.parse
method parses the string and constructs the JavaScript object described by it.",
- "You can request the JSON from freeCodeCamp's Cat Photo API. Here's the code you can put in your click event to do this:",
- "req=new XMLHttpRequest();", - "Here's a review of what each piece is doing. The JavaScript
req.open(\"GET\",'/json/cats.json',true);
req.send();
req.onload=function(){
json=JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML=JSON.stringify(json);
};
XMLHttpRequest
object has a number of properties and methods that are used to transfer data. First, an instance of the XMLHttpRequest
object is created and saved in the req
variable.",
- "Next, the open
method initializes a request - this example is requesting data from an API, therefore is a \"GET\" request. The second argument for open
is the URL of the API you are requesting data from. The third argument is a Boolean value where true
makes it an asynchronous request.",
- "The send
method sends the request. Finally, the onload
event handler parses the returned data and applies the JSON.stringify
method to convert the JavaScript object into a string. This string is then inserted as the message text.",
- "",
- "
XMLHttpRequest
.');",
- "assert(code.match(/\\.open\\(\\s*?('|\")GET\\1\\s*?,\\s*?('|\")\\/json\\/cats\\.json\\2\\s*?,\\s*?true\\s*?\\)/g), 'message: Your code should use the open
method to initialize a \"GET\" request to the freeCodeCamp Cat Photo API.');",
- "assert(code.match(/\\.send\\(\\s*\\)/g), 'message: Your code should use the send
method to send the request.');",
- "assert(code.match(/\\.onload\\s*=\\s*function\\(\\s*?\\)\\s*?{/g), 'message: Your code should have an onload
event handler set to a function.');",
- "assert(code.match(/JSON\\.parse\\(.*\\.responseText\\)/g), 'message: Your code should use the JSON.parse
method to parse the responseText
.');",
- "assert(code.match(/document\\.getElementsByClassName\\(\\s*?('|\")message\\1\\s*?\\)\\[0\\]\\.innerHTML\\s*?=\\s*?JSON\\.stringify\\(.+?\\)/g), 'message: Your code should get the element with class message
and change its inner HTML to the string of JSON data.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fae367417b2b2512be4",
- "title": "Access the JSON Data from an API",
- "description": [
- "In the previous challenge, you saw how to get JSON data from the freeCodeCamp Cat Photo API.",
- "Now you'll take a closer look at the returned data to better understand the JSON format. Recall some notation in JavaScript:",
- "[ ] -> Square brackets represent an array", - "Understanding the structure of the data that an API returns is important because it influences how you retrieve the values you need.", - "On the right, click the \"Get Message\" button to load the freeCodeCamp Cat Photo API JSON into the HTML.", - "The first and last character you see in the JSON data are square brackets
{ } -> Curly brackets represent an object
\" \" -> Double quotes represent a string. They are also used for key names in JSON
[ ]
. This means that the returned data is an array. The second character in the JSON data is a curly {
bracket, which starts an object. Looking closely, you can see that there are three separate objects. The JSON data is an array of three objects, where each object contains information about a cat photo.",
- "You learned earlier that objects contain \"key-value pairs\" that are separated by commas. In the Cat Photo example, the first object has \"id\":0
where \"id\" is a key and 0 is its corresponding value. Similarly, there are keys for \"imageLink\", \"altText\", and \"codeNames\". Each cat photo object has these same keys, but with different values.",
- "Another interesting \"key-value pair\" in the first object is \"codeNames\":[\"Juggernaut\",\"Mrs. Wallace\",\"ButterCup\"]
. Here \"codeNames\" is the key and its value is an array of three strings. It's possible to have arrays of objects as well as a key with an array as a value.",
- "Remember how to access data in arrays and objects. Arrays use bracket notation to access a specific index of an item. Objects use either bracket or dot notation to access the value of a given property. Here's an example that prints the \"altText\" of the first cat photo - note that the parsed JSON data in the editor is saved in a variable called json
:",
- "console.log(json[0].altText);", - "
// Prints \"A white cat wearing a green helmet shaped melon on its head.\"
codeNames
array. You should use bracket and dot notation on the object (which is saved in the variable json
) to access the value."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "
forEach
method to loop through the data since the cat photo objects are held in an array. As you get to each item, you can modify the HTML elements.",
- "First, declare an html variable with var html = \"\";
.",
- "Then, loop through the JSON, adding HTML to the variable that wraps the key names in strong
tags, followed by the value. When the loop is finished, you render it.",
- "Here's the code that does this:",
- "json.forEach(function(val) { var keys = Object.keys(val); html += \"<div class = 'cat'>\"; keys.forEach(function(key) { html += \"<strong>\" + key + \"</strong>: \" + val[key] + \"<br>\"; }); html += \"</div><br>\";});", - "
forEach
method to loop over the JSON data and create the HTML elements to display it.",
- "Here is some example JSON",
- "[ { \"id\":0, \"imageLink\":\"https://s3.amazonaws.com/freecodecamp/funny-cat.jpg\", \"altText\":\"A white cat wearing a green helmet shaped melon on its head. \", \"codeNames\":[ \"Juggernaut\", \"Mrs. Wallace\", \"Buttercup\" ] }]" - ], - "challengeSeed": [ - "", - "", - "
",
- "
html
variable');",
- "assert(code.match(/json\\.forEach/g), 'message: Your code should use a forEach
method to loop over the JSON data from the API.');",
- "assert(code.match(/.+<\\/strong>/g), 'message: Your code should wrap the key names in strong
tags.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fae367417b2b2512be6",
- "title": "Render Images from Data Sources",
- "description": [
- "The last few challenges showed that each object in the JSON array contains an imageLink
key with a value that is the URL of a cat's image.",
- "When you're looping through these objects, you can use this imageLink
property to display this image in an img
element.",
- "Here's the code that does this:",
- "html += \"<img src = '\" + val.imageLink + \"' \" + \"alt='\" + val.altText + \"'>\";
",
- "imageLink
and altText
properties in an img
tag."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "
imageLink
property to display the images.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7fae367417b2b2512be7",
- "title": "Pre-filter JSON to Get the Data You Need",
- "description": [
- "If you don't want to render every cat photo you get from the freeCodeCamp Cat Photo API, you can pre-filter the JSON before looping through it.",
- "Given that the JSON data is stored in an array, you can use the filter
method to filter out the cat whose \"id\" key has a value of 1.",
- "Here's the code to do this:",
- "json = json.filter(function(val) {", - "
return (val.id !== 1);
});
filter
the json data to remove the cat with the \"id\" value of 1."
- ],
- "challengeSeed": [
- "",
- "",
- "",
- "
filter
method.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7faf367417b2b2512be8",
- "title": "Get Geolocation Data to Find A User's GPS Coordinates",
- "description": [
- "Another cool thing you can do is access your user's current location. Every browser has a built in navigator that can give you this information.",
- "The navigator will get the user's current longitude and latitude.",
- "You will see a prompt to allow or block this site from knowing your current location. The challenge can be completed either way, as long as the code is correct.",
- "By selecting allow, you will see the text on the output phone change to your latitude and longitude.",
- "Here's code that does this:",
- "if (navigator.geolocation){", - "First, it checks if the
navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('data').innerHTML=\"latitude: \"+ position.coords.latitude + \"<br>longitude: \" + position.coords.longitude;
});
}
navigator.geolocation
object exists. If it does, the getCurrentPosition
method on that object is called, which initiates an asynchronous request for the user's position. If the request is successful, the callback function in the method runs. This function accesses the position
object's values for latitude and longitude using dot notation and updates the HTML.",
- "script
tags to check a user's current location and insert it into the HTML."
- ],
- "challengeSeed": [
- "",
- "navigator.geolocation
to access the user's current location.');",
- "assert(code.match(/position\\.coords\\.latitude/g), 'message: Your code should use position.coords.latitude
to display the user's latitudinal location.');",
- "assert(code.match(/position\\.coords\\.longitude/g), 'message: Your code should use position.coords.longitude
to display the user's longitudinal location.');",
- "assert(code.match(/document\\.getElementById\\(\\s*?('|\")data\\1\\s*?\\)\\.innerHTML/g), 'message: You should display the user's position within the data
div element.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- },
- {
- "id": "587d7faf367417b2b2512be9",
- "title": "Post Data with the JavaScript XMLHttpRequest Method",
- "description": [
- "In the previous examples, you received data from an external resource. You can also send data to an external resource, as long as that resource supports AJAX requests and you know the URL.",
- "JavaScript's XMLHttpRequest
method is also used to post data to a server. Here's an example:",
- "req=new XMLHttpRequest();", - "You've seen several of these methods before. Here the
req.open(\"POST\",url,true);
req.setRequestHeader('Content-Type','text/plain');
req.onreadystatechange=function(){
if(req.readyState==4 && req.status==200){
document.getElementsByClassName('message')[0].innerHTML=req.responseText;
}
};
req.send(userName);
open
method initializes the request as a \"POST\" to the given URL of the external resource, and uses the true
Boolean to make it asynchronous.",
- "The setRequestHeader
method sets the value of an HTTP request header, which contains information about the sender and the request. It must be called after the open
method, but before the send
method. The two parameters are the name of the header and the value to set as the body of that header.",
- "Next, the onreadystatechange
event listener handles a change in the state of the request. A readyState
of 4 means the operation is complete, and a status
of 200 means it was a successful request. The document's HTML can be updated.",
- "Finally, the send
method sends the request with the userName
value, which was given by the user in the input
field.",
- "",
- " ",
- "
XMLHttpRequest
.');",
- "assert(code.match(/\\.open\\(\\s*?('|\")POST\\1\\s*?,\\s*?url\\s*?,\\s*?true\\s*?\\)/g), 'message: Your code should use the open
method to initialize a \"POST\" request to the server.');",
- "assert(code.match(/\\.setRequestHeader\\(\\s*?('|\")Content-Type\\1\\s*?,\\s*?('|\")text\\/plain\\2\\s*?\\)/g), 'message: Your code should use the setRequestHeader
method.');",
- "assert(code.match(/\\.onreadystatechange\\s*?=/g), 'message: Your code should have an onreadystatechange
event handler set to a function.');",
- "assert(code.match(/document\\.getElementsByClassName\\(\\s*?('|\")message\\1\\s*?\\)\\[0\\]\\.innerHTML\\s*?=\\s*?.+?\\.responseText/g), 'message: Your code should get the element with class message
and change its inner HTML to the responseText
.');",
- "assert(code.match(/\\.send\\(\\s*?userName\\s*?\\)/g), 'message: Your code should use the send
method.');"
- ],
- "solutions": [],
- "hints": [],
- "type": "waypoint",
- "releasedOn": "Feb 17, 2017",
- "challengeType": 0,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json b/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json
deleted file mode 100644
index eca6eab092..0000000000
--- a/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json
+++ /dev/null
@@ -1,174 +0,0 @@
-{
- "name": "API and Microservice Projects",
- "order": 4,
- "time": "150 hours",
- "helpRoom": "HelpBackend",
- "challenges": [
- {
- "id": "bd7158d8c443edefaeb5bdef",
- "title": "Timestamp Microservice",
- "description": [
- "Build a full stack JavaScript app that is functionally similar to this: https://curse-arrow.glitch.me/.",
- "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.",
- "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "I can pass a string as a parameter, and it will check to see whether that string contains either a unix timestamp or a natural language date (example: January 1, 2016).",
- "testString": ""
- },
- {
- "text": "If it does, it returns both the Unix timestamp and the natural language form of that date.",
- "testString": ""
- },
- {
- "text": "If it does not contain a date or Unix timestamp, it returns null for those properties.",
- "testString": ""
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "isRequired": true,
- "releasedOn": "January 1, 2016",
- "translations": {
- "es": {
- "title": "Microservicio de Marca Temporal"
- }
- }
- },
- {
- "id": "bd7158d8c443edefaeb5bdff",
- "title": "Request Header Parser Microservice",
- "description": [
- "Build a full stack JavaScript app that is functionally similar to this: https://dandelion-roar.glitch.me/.",
- "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.",
- "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "I can get the IP address, language and operating system for my browser.",
- "testString": ""
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "isRequired": true,
- "releasedOn": "January 1, 2016",
- "translations": {
- "es": {
- "title": "Microservicio para analizar el encabezado de una petición"
- }
- }
- },
- {
- "id": "bd7158d8c443edefaeb5bd0e",
- "title": "URL Shortener Microservice",
- "description": [
- "Build a full stack JavaScript app that is functionally similar to this: https://thread-paper.glitch.me/.",
- "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.",
- "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "I can pass a URL as a parameter and I will receive a shortened URL in the JSON response.",
- "testString": ""
- },
- {
- "text": "If I pass an invalid URL that doesn't follow the valid http://www.example.com format, the JSON response will contain an error instead.",
- "testString": ""
- },
- {
- "text": "When I visit that shortened URL, it will redirect me to my original link.",
- "testString": ""
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "isRequired": true,
- "releasedOn": "January 1, 2016",
- "translations": {
- "es": {
- "title": "Microservicio para acortar URLs"
- }
- }
- },
- {
- "id": "5a8b073d06fa14fcfde687aa",
- "title": "Exercise Tracker",
- "description": [
- "Build a full stack JavaScript app that is functionally similar to this: https://fuschia-custard.glitch.me/.",
- "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.",
- "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "I can create a user by posting form data username to /api/exercise/new-user and returned will be an object with username and _id
.",
- "testString": ""
- },
- {
- "text": "I can get an array of all users by getting api/exercise/users with the same info as when creating a user.",
- "testString": ""
- },
- {
- "text": "I can add an exercise to any user by posting form data userId(_id), description, duration, and optionally date to /api/exercise/add. If no date supplied it will use current date. App will return the user object with the exercise fields added.",
- "testString": ""
- },
- {
- "text": "I can retrieve a full exercise log of any user by getting /api/exercise/log with a parameter of userId(_id). App will return the user object with added array log and count (total exercise count).",
- "testString": ""
- },
- {
- "text": "I can retrieve part of the log of any user by also passing along optional parameters of from & to or limit. (Date format yyyy-mm-dd, limit = int)",
- "testString": ""
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "isRequired": true,
- "releasedOn": "February 17, 2017",
- "translations": {
- "es": {
- "title": "Capa de abstracción para buscar imágenes"
- }
- }
- },
- {
- "id": "bd7158d8c443edefaeb5bd0f",
- "title": "File Metadata Microservice",
- "description": [
- "Build a full stack JavaScript app that is functionally similar to this: https://purple-paladin.glitch.me/.",
- "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.",
- "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "I can submit a FormData object that includes a file upload.",
- "testString": ""
- },
- {
- "text": "When I submit something, I will receive the file size in bytes within the JSON response.",
- "testString": ""
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "isRequired": true,
- "releasedOn": "January 1, 2016",
- "translations": {
- "es": {
- "title": "Microservicio de metadatos de archivos"
- }
- }
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json b/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json
deleted file mode 100644
index ebb11edba5..0000000000
--- a/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json
+++ /dev/null
@@ -1,310 +0,0 @@
-{
- "name": "Basic Node and Express",
- "order": 2,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7fb0367417b2b2512bec",
- "title": "Introduction to the Basic Node and Express Challenges",
- "description": [
- "",
- "",
- "Node.js is a JavaScript tool that allows developers to write backend (server-side) programs in JavaScript. Node.js comes with a handful of built-in modules—small, independent programs—that help facilitate this purpose. Some of the core modules include:\"Hello World\"
should be in the console",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/hello-console').then(data => { assert.isTrue(data.passed, '\"Hello World\" is not in the server console'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb0367417b2b2512bee",
- "title": "Start a Working Express Server",
- "description": [
- "In the first two lines of the file myApp.js you can see how it’s easy to create an Express app object. This object has several methods, and we will learn many of them in these challenges. One fundamental method is app.listen(port)
. It tells your server to listen on a given port, putting it in running state. You can see it at the bottom of the file. It is inside comments because for testing reasons we need the app to be running in background. All the code that you may want to add goes between these two fundamental parts. Glitch stores the port number in the environemet variable process.env.PORT
. Its value is 3000
.",
- "Let’s serve our first string! In Express, routes takes the following structure: app.METHOD(PATH, HANDLER)
. METHOD is an http method in lowercase. PATH is a relative path on the server (it can be a string, or even a regular expression). HANDLER is a function that Express calls when the route is matched.",
- "Handlers take the form function(req, res) {...}
, where req is the request object, and res is the response object. For example, the handler",
- "function(req, res) {", - "will serve the string 'Response String'.", - "Use the
res.send('Response String');
}
app.get()
method to serve the string Hello Express, to GET requests matching the / root path. Be sure that your code works by looking at the logs, then see the results in your browser, clicking the button ‘Show Live’ in the Glitch UI."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Your app should serve the string 'Hello Express'",
- "testString": "getUserInput => $.get(getUserInput('url')).then(data => { assert.equal(data, 'Hello Express', 'Your app does not serve the text \"Hello Express\"'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb0367417b2b2512bef",
- "title": "Serve an HTML File",
- "description": [
- "We can respond with a file using the method res.sendFile(path)
.",
- "You can put it inside the app.get('/', ...)
route handler. Behind the scenes this method will set the appropriate headers to instruct your browser on how to handle the file you want to send, according to its type. Then it will read and send the file. This method needs an absolute file path. We recommend you to use the Node global variable __dirname
to calculate the path.",
- "e.g. absolutePath = __dirname + relativePath/file.ext
.",
- "The file to send is /views/index.html
. Try to ‘Show Live’ your app, you should see a big HTML heading (and a form that we will use later…), with no style applied.",
- "Note: You can edit the solution of the previous challenge, or create a new one. If you create a new solution, keep in mind that Express evaluates the routes from top to bottom. It executes the handler for the first match. You have to comment out the preceding solution, or the server will keep responding with a string."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Your app should serve the file views/index.html",
- "testString": "getUserInput => $.get(getUserInput('url')).then(data => { assert.match(data, /express.static(path)
, where the parameter is the absolute path of the folder containing the assets. If don’t know what a middleware is, don’t worry. We’ll discuss about it later in details. Basically middlewares are functions that intercept route handlers, adding some kind of information. A middleware needs to be mounted using the method app.use(path, middlewareFunction)
. The first path argument is optional. If you don’t pass it, the middleware will be executed for all the requests.",
- "Mount the express.static()
middleware for all the requests with app.use()
. The absolute path to the assets folder is __dirname + /public
.",
- "Now your app should be able to serve a CSS stylesheet. From outside the public folder will appear mounted to the root directory. Your front-page should look a little better now!"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Your app should serve asset files from the /public
directory",
- "testString": "getUserInput => $.get(getUserInput('url') + '/style.css').then(data => { assert.match(data, /body\\s*\\{[^\\}]*\\}/, 'Your app does not serve static assets'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb1367417b2b2512bf1",
- "title": "Serve JSON on a Specific Route",
- "description": [
- "While an HTML server serves (you guessed it!) HTML, an API serves data. A REST (REpresentational State Transfer) API allows data exchange in a simple way, without the need for clients to know any detail about the server. The client only needs to know where the resource is (the URL), and the action it wants to perform on it (the verb). The GET verb is used when you are fetching some information, without modifying anything. These days, the preferred data format for moving information around the web is JSON. Simply put, JSON is a convenient way to represent a JavaScript object as a string, so it can be easily transmitted.",
- "Let's create a simple API by creating a route that responds with JSON at the path /json
. You can do it as usual, with the app.get()
method. Inside the route handler use the method res.json()
, passing in an object as an argument. This method closes the request-response loop, returning the data. Behind the scenes it converts a valid JavaScript object into a string, then sets the appropriate headers to tell your browser that you are serving JSON, and sends the data back. A valid object has the usual structure {key: data}
. Data can ba a number, a string, a nested object or an array. Data can also be a variable or the result of a function call; in which case it will be evaluated before being converted into a string.",
- "Serve the object {\"message\": \"Hello json\"}
as a response in JSON format, to the GET requests to the route /json
. Then point your browser to your-app-url/json, you should see the message on the screen."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "The endpoint /json
should serve the json object {\"message\": \"Hello json\"}
",
- "testString": "getUserInput => $.get(getUserInput('url') + '/json').then(data => { assert.equal(data.message, 'Hello json', 'The \\'/json\\' endpoint does not serve the right data'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb1367417b2b2512bf2",
- "title": "Use the .env File",
- "description": [
- "The .env
file is a hidden file that is used to pass environment variables to your application. This file is secret, no one but you can access it, and it can be used to store data that you want to keep private or hidden. For example, you can store API keys from external services or your database URI. You can also use it to store configuration options. By setting configuration options, you can change the behavior of your application, without the need to rewrite some code.",
- "The environment variables are accessible from the app as process.env.VAR_NAME
. The process.env
object is a global Node object, and variables are passed as strings. By convention, the variable names are all uppercase, with words separated by an underscore. The .env
is a shell file, so you don’t need to wrap names or values in quotes. It is also important to note that there cannot be space around the equals sign when you are assigning values to your variables, e.g. VAR_NAME=value
. Usually, you will put each variable definition on a separate line.",
- "Let's add an environment variable as a configuration option. Store the variable MESSAGE_STYLE=uppercase
in the .env
file. Then tell the GET /json
route handler that you created in the last challenge to transform the response object’s message to uppercase if process.env.MESSAGE_STYLE
equals uppercase
. The response object should become {\"message\": \"HELLO JSON\"}
."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "The response of the endpoint /json
should change according to the environment variable MESSAGE_STYLE
",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/use-env-vars').then(data => { assert.isTrue(data.passed, 'The response of \"/json\" does not change according to MESSAGE_STYLE'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb1367417b2b2512bf3",
- "title": "Implement a Root-Level Request Logger Middleware",
- "description": [
- "Before we introduced the express.static()
middleware function. Now it’s time to see what middleware is, in more detail. Middleware functions are functions that take 3 arguments: the request object, the response object, and the next function in the application’s request-response cycle. These functions execute some code that can have side effects on the app, and usually add informations to the request or response objects. They can also end the cycle sending the response, when some condition is met. If they don’t send the response, when they are done they start the execution of the next function in the stack. This is triggered calling the 3rd argument next()
. More information in the express documentation.",
- "Look at the following example :",
- "function(req, res, next) {", - "Let’s suppose we mounted this function on a route. When a request matches the route, it displays the string “I’m a middleware…”. Then it executes the next function in the stack.", - "In this exercise we are going to build a root-level middleware. As we have seen in challenge 4, to mount a middleware function at root level we can use the method
console.log(\"I'm a middleware...\");
next();
}
app.use(<mware-function>)
. In this case the function will be executed for all the requests, but you can also set more specific conditions. For example, if you want a function to be executed only for POST requests, you could use app.post(<mware-function>)
. Analogous methods exist for all the http verbs (GET, DELETE, PUT, …).",
- "Build a simple logger. For every request, it should log in the console a string taking the following format: method path - ip
. An example would look like: GET /json - ::ffff:127.0.0.1
. Note that there is a space between method
and path
and that the dash separating path
and ip
is surrounded by a space on either side. You can get the request method (http verb), the relative route path, and the caller’s ip from the request object, using req.method
, req.path
and req.ip
. Remember to call next()
when you are done, or your server will be stuck forever. Be sure to have the ‘Logs’ opened, and see what happens when some request arrives…",
- "Hint: Express evaluates functions in the order they appear in the code. This is true for middleware too. If you want it to work for all the routes, it should be mounted before them."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Root level logger middleware should be active",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/root-middleware-logger').then(data => { assert.isTrue(data.passed, 'root-level logger is not working as expected'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb1367417b2b2512bf4",
- "title": "Chain Middleware to Create a Time Server",
- "description": [
- "Middleware can be mounted at a specific route using app.METHOD(path, middlewareFunction)
. Middleware can also be chained inside route definition.",
- "Look at the following example:",
- "app.get('/user', function(req, res, next) {", - "This approach is useful to split the server operations into smaller units. That leads a to a better app structure, and the possibility to reuse code in different places. This approach can also be used to perform some validation on the data. At each point of the middleware stack you can block the execution of the current chain and pass control to functions specifically designed to handle errors. Or you can pass control to the next matching route, to handle special cases. We will see how in the advanced Express section.", - "In the route
req.user = getTheUserSync(); // Hypotetical synchronous operation
next();
}, function(req, res) {
res.send(req.user);
})
app.get('/now', ...)
chain a middleware function and the final handler. In the middleware function you should add the current time to the request object in the req.time
key. You can use new Date().toString()
. In the handler, respond with a JSON object, taking the structure {time: req.time}
.",
- "Hint: The test will not pass if you don’t chain the middleware. If you mount the function somewhere else, the test will fail, even if the output result is correct."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "The /now endpoint should have mounted middleware",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/chain-middleware-time').then(data => { assert.equal(data.stackLength, 2, '\"/now\" route has no mounted middleware'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "The /now endpoint should return a time that is +/- 20 secs from now",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/chain-middleware-time').then(data => { var now = new Date(); assert.isAtMost(Math.abs(new Date(data.time) - now), 20000, 'the returned time is not between +- 20 secs from now'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb2367417b2b2512bf5",
- "title": "Get Route Parameter Input from the Client",
- "description": [
- "When building an API, we have to allow users to comunicate us what they want to get from our service. For example, if the client is requesting information about a user stored in the database, they need a way to let us know which user they're interested in. One possible way to achieve this result is using route parameters. Route parameters are named segments of the URL, delimited by slashes (/). Each segment captures the value of the part of the URL which matches its position. The captured values can be found in the req.params
object.",
- "route_path: '/user/:userId/book/:bookId'", - "Build an echo server, mounted at the route
actual_request_URL: '/user/546/book/6754'
req.params: {userId: '546', bookId: '6754'}
GET /:word/echo
. Respond with a JSON object, taking the structure {echo: word}
. You can find the word to be repeated at req.params.word
. You can test your route from your browser's address bar, visiting some matching routes, e.g. your-app-rootpath/freecodecamp/echo"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Test 1 : Your echo server should repeat words correctly",
- "testString": "getUserInput => $.get(getUserInput('url') + '/eChOtEsT/echo').then(data => { assert.equal(data.echo, 'eChOtEsT', 'Test 1: the echo server is not working as expected') }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "Test 2 : Your echo server should repeat words correctly",
- "testString": "getUserInput => $.get(getUserInput('url') + '/ech0-t3st/echo').then(data => { assert.equal(data.echo, 'ech0-t3st', 'Test 2: the echo server is not working as expected') }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb2367417b2b2512bf6",
- "title": "Get Query Parameter Input from the Client",
- "description": [
- "Another common way to get input from the client is by encoding the data after the route path, using a query string. The query string is delimited by a question mark (?), and includes field=value couples. Each couple is separated by an ampersand (&). Express can parse the data from the query string, and populate the object req.query
. Some characters cannot be in URLs, they have to be encoded in a different format before you can send them. If you use the API from JavaScript, you can use specific methods to encode/decode these characters.",
- "route_path: '/library'", - "Build an API endpoint, mounted at
actual_request_URL: '/library?userId=546&bookId=6754'
req.query: {userId: '546', bookId: '6754'}
GET /name
. Respond with a JSON document, taking the structure { name: 'firstname lastname'}
. The first and last name parameters should be encoded in a query string e.g. ?first=firstname&last=lastname
.",
- "TIP: In the following exercise we are going to receive data from a POST request, at the same /name
route path. If you want you can use the method app.route(path).get(handler).post(handler)
. This syntax allows you to chain different verb handlers on the same path route. You can save a bit of typing, and have cleaner code."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Test 1 : Your API endpoint should respond with the correct name",
- "testString": "getUserInput => $.get(getUserInput('url') + '/name?first=Mick&last=Jagger').then(data => { assert.equal(data.name, 'Mick Jagger', 'Test 1: \"GET /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "Test 2 : Your APi endpoint should respond with the correct name",
- "testString": "getUserInput => $.get(getUserInput('url') + '/name?last=Richards&first=Keith').then(data => { assert.equal(data.name, 'Keith Richards', 'Test 2: \"GET /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb2367417b2b2512bf7",
- "title": "Use body-parser to Parse POST Requests",
- "description": [
- "Besides GET there is another common http verb, it is POST. POST is the default method used to send client data with HTML forms. In the REST convention POST is used to send data to create new items in the database (a new user, or a new blog post). We don’t have a database in this project, but we are going to learn how to handle POST requests anyway.",
- "In these kind of requests the data doesn’t appear in the URL, it is hidden in the request body. This is a part of the HTML request, also called payload. Since HTML is text based, even if you don’t see the data, it doesn’t mean that they are secret. The raw content of an HTTP POST request is shown below:",
- "POST /path/subpath HTTP/1.0", - "As you can see the body is encoded like the query string. This is the default format used by HTML forms. With Ajax we can also use JSON to be able to handle data having a more complex structure. There is also another type of encoding: multipart/form-data. This one is used to upload binary files.", - "In this exercise we will use an urlencoded body.", - "To parse the data coming from POST requests, you have to install a package: the body-parser. This package allows you to use a series of middleware, which can decode data in different formats. See the docs here.", - "Install the body-parser module in your package.json. Then require it at the top of the file. Store it in a variable named bodyParser.", - "The middleware to handle url encoded data is returned by
From: john@example.com
User-Agent: someBrowser/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
name=John+Doe&age=25
bodyParser.urlencoded({extended: false})
. extended=false
is a configuration option that tells the parser to use the classic encoding. When using it, values can be only strings or arrays. The extended version allows more data flexibility, but it is outmatched by JSON. Pass to app.use()
the function returned by the previous method call. As usual, the middleware must be mounted before all the routes which need it."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "The 'body-parser' middleware should be mounted",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/add-body-parser').then(data => { assert.isAbove(data.mountedAt, 0, '\"body-parser\" is not mounted correctly') }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb2367417b2b2512bf8",
- "title": "Get Data from POST Requests",
- "description": [
- "Mount a POST handler at the path /name
. It’s the same path as before. We have prepared a form in the html frontpage. It will submit the same data of exercise 10 (Query string). If the body-parser is configured correctly, you should find the parameters in the object req.body
. Have a look at the usual library example:",
- "route: POST '/library'", - "Respond with the same JSON object as before:
urlencoded_body: userId=546&bookId=6754
req.body: {userId: '546', bookId: '6754'}
{name: 'firstname lastname'}
. Test if your endpoint works using the html form we provided in the app frontpage.",
- "Tip: There are several other http methods other than GET and POST. And by convention there is a corrispondence between the http verb, and the operation you are going to execute on the server. The conventional mapping is:",
- "POST (sometimes PUT) - Create a new resource using the information sent with the request,",
- "GET - Read an existing resource without modifying it,",
- "PUT or PATCH (sometimes POST) - Update a resource using the data sent,",
- "DELETE => Delete a resource.",
- "There are also a couple of other methods which are used to negotiate a connection with the server. Except from GET, all the other methods listed above can have a payload (i.e. the data into the request body). The body-parser middleware works with these methods as well."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Test 1 : Your API endpoint should respond with the correct name",
- "testString": "getUserInput => $.post(getUserInput('url') + '/name', {first: 'Mick', last: 'Jagger'}).then(data => { assert.equal(data.name, 'Mick Jagger', 'Test 1: \"POST /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "Test 2 : Your API endpoint should respond with the correct name",
- "testString": "getUserInput => $.post(getUserInput('url') + '/name', {first: 'Keith', last: 'Richards'}).then(data => { assert.equal(data.name, 'Keith Richards', 'Test 2: \"POST /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json b/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json
deleted file mode 100644
index dc28fbf1d7..0000000000
--- a/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json
+++ /dev/null
@@ -1,305 +0,0 @@
-{
- "name": "Managing Packages with npm",
- "order": 1,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7fb3367417b2b2512bfa",
- "title": "Introduction to the Managing Packages with npm Challenges",
- "description": [
- "",
- "",
- "The Node Package Manager (npm) is a command-line tool used by developers to share and control modules (or packages) of JavaScript code written for use with Node.js.package.json
file. This file lists the package dependencies for your project. Since npm packages are regularly updated, the package.json
file allows you to set specific version numbers for each dependency. This ensures that updates to a package don't break your project.node_modules
. These packages can be installed in two ways:node_modules
folder, accessible by all projects.node_modules
folder, accessible only to that project.\"author\": \"Jane Doe\",
",
- "Instructions",
- "Add your name to the author-field in the package.json of your Glitch project.",
- "Remember that you’re writing JSON.",
- "All field-names must use double-quotes (\"), e.g. \"author\"",
- "All fields must be separated with a comma (,)"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "package.json should have a valid \"author\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.author, '\"author\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb3367417b2b2512bfc",
- "title": "Add a Description to Your package.json",
- "description": [
- "The next part of a good package.json is the description-field, where a short but informative description about your project belongs.",
- "If you some day plan to publishing a package to npm, remember that this is the string that should sell your idea to the user when they decide whether to install your package or not. However, that’s not the only use case for the description: Since it’s a great way to summarize what a project does, it’s just as important for your normal Node.js-projects to help other developers, future maintainers or even your future self understand the project quickly.",
- "Regardless of what you plan for your project, a description is definitely recommended. Let’s add something similar to this:",
- "\"description\": \"A project that does something awesome\",
",
- "Instructions",
- "Add a description to the package.json in your Glitch project.",
- "Remember to use double-quotes for field-names (\") and commas (,) to separate fields."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "package.json should have a valid \"description\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.description, '\"description\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb4367417b2b2512bfd",
- "title": "Add Keywords to Your package.json",
- "description": [
- "The keywords-field is where you can describe your project using related keywords.",
- "Example",
- "\"keywords\": [ \"descriptive\", \"related\", \"words\" ],
",
- "As you can see, this field is structured as an array of double-quoted strings.",
- "Instructions",
- "Add an array of suitable strings to the keywords-field in the package.json of your Glitch project.",
- "One of the keywords should be freecodecamp."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "package.json should have a valid \"keywords\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.keywords, '\"keywords\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"keywords\" field should be an Array",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.isArray(packJson.keywords, '\"keywords\" is not an array'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"keywords\" should include \"freecodecamp\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.include(packJson.keywords, 'freecodecamp', '\"keywords\" does not include \"freecodecamp\"'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb4367417b2b2512bfe",
- "title": "Add a License to Your package.json",
- "description": [
- "TODO: This challenge could be used to inspire more people to develop OSS - we should really improve this description.",
- "The license-field is where you inform users of your project what they are allowed to do with it.",
- "Some common licenses for open source projects include MIT and BSD. http://choosealicense.com is a great resource if you want to learn more about what license could fit your project.",
- "License information is not required. Copyright laws in most countries will give you ownership of what you create by default. However, it’s always a good practice to explicitly state what users can and can’t do.",
- "Example",
- "\"license\": \"MIT\",
",
- "Instructions",
- "Fill the license-field in the package.json of your Glitch project as you find suitable."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "package.json should have a valid \"license\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.license, '\"license\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb4367417b2b2512bff",
- "title": "Add a Version to Your package.json",
- "description": [
- "The version is together with name one of the required fields in a package.json. This field describes the current version of your project.",
- "Example",
- "\"version\": \"1.2\",
",
- "Instructions",
- "Add a version to the package.json in your Glitch project."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "package.json should have a valid \"version\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.version, '\"version\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb4367417b2b2512c00",
- "title": "Expand Your Project with External Packages from npm",
- "description": [
- "One of the biggest reasons to use a package manager is their powerful dependency management. Instead of manually having to make sure that you get all dependencies whenever you set up a project on a new computer, npm automatically installs everything for you. But how can npm know exactly what your project needs? Meet the dependencies-section of your package.json.",
- "In the dependencies-section, packages your project require are stored using the following format:",
- "\"dependencies\": {
",
- " \"package-name\": \"version\",
",
- " \"express\": \"4.14.0\"
",
- "}
",
- "Instructions",
- "Add version 2.14.0 of the package moment to the dependencies-field of your package.json",
- "Moment is a handy library for working with time and dates."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"moment\" version should be \"2.14.0\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.14\\.0/, 'Wrong version of \"moment\" installed. It should be 2.14.0'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb5367417b2b2512c01",
- "title": "Manage npm Dependencies By Understanding Semantic Versioning",
- "description": [
- "Versions of the npm packages in the dependencies-section of your package.json follow what’s called Semantic Versioning (SemVer), an industry standard for software versioning aiming to make it easier to manage dependencies. Libraries, frameworks or other tools published on npm should use SemVer in order to clearly communicate what kind of changes that projects who depend on the package can expect if they update.",
- "SemVer doesn’t make sense in projects without public APIs - so unless your project is similar to the examples above, use another versioning format.",
- "So why do you need to understand SemVer?",
- "Knowing SemVer can be useful when you develop software that use external dependencies (which you almost always do). One day, your understanding of these numbers will save you from accidentally introducing breaking changes to your project without understanding why things “that worked yesterday” suddenly doesn’t.",
- "This is how Semantic Versioning works according to the official website:",
- "Given a version number MAJOR.MINOR.PATCH, increment the:",
- "MAJOR version when you make incompatible API changes,",
- "MINOR version when you add functionality in a backwards-compatible manner, and",
- "PATCH version when you make backwards-compatible bug fixes.",
- "This means that PATCHes are bug fixes and MINORs add new features but neither of them break what worked before. Finally, MAJORs add changes that won’t work with earlier versions.",
- "Example",
- "A semantic version number: 1.3.8",
- "Instructions",
- "In the dependencies-section of your package.json, change the version of moment to match MAJOR version 2, MINOR version 10 and PATCH version 2"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"moment\" version should be \"2.10.2\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.10\\.2/, 'Wrong version of \"moment\". It should be 2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb5367417b2b2512c02",
- "title": "Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency",
- "description": [
- "In the last challenge, we told npm to only include a specific version of a package. That’s a useful way to freeze your dependencies if you need to make sure that different parts of your project stay compatible with each other. But in most use cases you don’t want to miss bug fixes, since they often include important security patches and (hopefully) don’t break things in doing so.",
- "To allow a npm dependency to get updated to the latest PATCH-version, you can prefix the dependency’s version with the tilde-character (~). In package.json, our current rule for how npm may upgrade moment is to use a specific version only (2.10.2), but we want to allow the latest 2.10.x-version.",
- "Example",
- "\"some-package-name\": \"~1.3.8\" allows updates to any 1.3.x version.
",
- "Instructions",
- "Use the tilde-character (~) to prefix the version of moment in your dependencies and allow npm to update it to any new PATCH release.",
- "Note that the version numbers themselves not should be changed."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"moment\" version should match \"~2.10.2\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\~2\\.10\\.2/, 'Wrong version of \"moment\". It should be ~2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb5367417b2b2512c03",
- "title": "Use the Caret-Character to Use the Latest Minor Version of a Dependency",
- "description": [
- "Similar to how the tilde (~) we learned about in the last challenge allow npm to install the latest PATCH for a dependency, the caret (^) allows npm to install future updates as well. The difference is that the caret will allow both MINOR updates and PATCHes.",
- "At the moment, your current version of moment should be ~2.10.2 which allows npm to install to the latest 2.10.x-version. If we instead were to use the caret (^) as our version prefix, npm would instead be allowed to update to any 2.x.x-version.",
- "Example",
- "\"some-package-name\": \"^1.3.8\" allows updates to any 1.x.x version.
",
- "Instructions",
- "Use the caret-character (^) to prefix the version of moment in your dependencies and allow npm to update it to any new MINOR release.",
- "Note that the version numbers themselves not should be changed."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
- },
- {
- "text": "\"moment\" version should match \"^2.x.x\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\^2\\./, 'Wrong version of \"moment\". It should be ^2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb5367417b2b2512c04",
- "title": "Remove a Package from Your Dependencies",
- "description": [
- "Now you’ve tested a few ways you can manage dependencies of your project by using the package.json's dependencies-section. You’ve included external packages by adding them to the file and even told npm what types of versions you want by using special characters as the tilde (~) or the caret (^).",
- "But what if you want to remove an external package that you no longer need? You might already have guessed it - Just remove the corresponding \"key\": value-pair for that from your dependencies.",
- "This same method applies to removing other fields in your package.json as well",
- "Instructions",
- "Remove the package moment from your dependencies.",
- "Make sure you have the right amount of commas after removing it."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "\"dependencies\" should not include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.notProperty(packJson.dependencies, 'moment', '\"dependencies\" still includes \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json b/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json
deleted file mode 100644
index ac2aabd911..0000000000
--- a/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json
+++ /dev/null
@@ -1,324 +0,0 @@
-{
- "name": "MongoDB and Mongoose",
- "order": 3,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "587d7fb5367417b2b2512c05",
- "title": "Introduction to the MongoDB and Mongoose Challenges",
- "description": [
- "",
- "",
- "MongoDB is a database that stores data records (documents) for use by an application. Mongo is a non-relational, \"NoSQL\" database. This means Mongo stores all data associated within one record, instead of storing it across many preset tables as in a SQL database. Some benefits of this storage model are:mongodb://dbuser:dbpassword@ds0$PORT$.mlab.com:$PORT$/$DATABASE-NAME$
.- Person Prototype -
",
- "--------------------
",
- "name : string [required]
",
- "age : number
",
- "favoriteFoods : array of strings (*)
",
- "Use the mongoose basic schema types. If you want you can also add",
- "more fields, use simple validators like required or unique,",
- "and set default values. See the mongoose docs.",
- "[C]RUD Part I - CREATE",
- "Note: Glitch is a real server, and in real servers the interactions with the db happen in handler functions. These function are executed when some event happens (e.g. someone hits an endpoint on your API). We’ll follow the same approach in these exercises. The done() function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating or deleting. It’s following the Node convention and should be called as done(null, data) on success, or done(err) on error.",
- "Warning - When interacting with remote services, errors may occur !",
- "/* Example */
",
- "var someFunc = function(done) {
",
- " //... do something (risky) ...
",
- " if(error) return done(error);
",
- " done(null, result);
",
- "};
"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Creating an instance from a mongoose schema should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/mongoose-model', {name: 'Mike', age: 28, favoriteFoods: ['pizza', 'cheese']}).then(data => { assert.equal(data.name, 'Mike', '\"model.name\" is not what expected'); assert.equal(data.age, '28', '\"model.age\" is not what expected'); assert.isArray(data.favoriteFoods, '\"model.favoriteFoods\" is not an Array'); assert.include(data.favoriteFoods, 'pizza', '\"model.favoriteFoods\" does not include the expected items'); assert.include(data.favoriteFoods, 'cheese', '\"model.favoriteFoods\" does not include the expected items'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb6367417b2b2512c09",
- "title": "Create and Save a Record of a Model",
- "description": [
- "Create a document instance using the Person constructor you build before. Pass to the constructor an object having the fields name, age, and favoriteFoods. Their types must be conformant to the ones in the Person Schema. Then call the method document.save() on the returned document instance. Pass to it a callback using the Node convention. This is a common pattern, all the following CRUD methods take a callback function like this as the last argument.",
- "/* Example */
",
- "// ...
",
- "person.save(function(err, data) {
",
- "// ...do your stuff here...
",
- "});
"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Creating and saving a db item should succeed",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/create-and-save-person').then(data => { assert.isString(data.name, '\"item.name\" should be a String'); assert.isNumber(data.age, '28', '\"item.age\" should be a Number'); assert.isArray(data.favoriteFoods, '\"item.favoriteFoods\" should be an Array'); assert.equal(data.__v, 0, 'The db item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb7367417b2b2512c0a",
- "title": "Create Many Records with model.create()",
- "description": [
- "Sometimes you need to create many instances of your models, e.g. when seeding a database with initial data. Model.create() takes an array of objects like [{name: 'John', ...}, {...}, ...] as the first argument, and saves them all in the db. Create many people with Model.create(), using the function argument arrayOfPeople."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Creating many db items at once should succeed",
- "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/create-many-people', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'John', age: 24, favoriteFoods: ['pizza', 'salad']}, {name: 'Mary', age: 21, favoriteFoods: ['onions', 'chicken']}])}).then(data => { assert.isArray(data, 'the response should be an array'); assert.equal(data.length, 2, 'the response does not contain the expected number of items'); assert.equal(data[0].name, 'John', 'The first item is not correct'); assert.equal(data[0].__v, 0, 'The first item should be not previously edited'); assert.equal(data[1].name, 'Mary', 'The second item is not correct'); assert.equal(data[1].__v, 0, 'The second item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb7367417b2b2512c0b",
- "title": "Use model.find() to Search Your Database",
- "description": [
- "Find all the people having a given name, using Model.find() -> [Person]",
- "In its simplest usage, Model.find() accepts a query document (a JSON object ) as the first argument, then a callback. It returns an array of matches. It supports an extremely wide range of search options. Check it in the docs. Use the function argument personName as search key."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Find all items corresponding to a criteria should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-all-by-name', {name: 'r@nd0mN4m3', age: 24, favoriteFoods: ['pizza']}).then(data => { assert.isArray(data, 'the response should be an Array'); assert.equal(data[0].name, 'r@nd0mN4m3', 'item.name is not what expected'); assert.equal(data[0].__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb7367417b2b2512c0c",
- "title": "Use model.findOne() to Return a Single Matching Document from Your Database",
- "description": [
- "Model.findOne() behaves like .find(), but it returns only one document (not an array), even if there are items. It is especially useful when searching by properties that you have declared as unique. Find just one person which has a certain food in her favorites, using Model.findOne() -> Person. Use the function argument food as search key."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Find one item should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-one-by-food', {name: 'Gary', age: 46, favoriteFoods: ['chicken salad']}).then(data => { assert.equal(data.name, 'Gary', 'item.name is not what expected'); assert.deepEqual(data.favoriteFoods, ['chicken salad'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb7367417b2b2512c0d",
- "title": "Use model.findById() to Search Your Database By _id",
- "description": [
- "When saving a document, mongodb automatically adds the field _id, and set it to a unique alphanumeric key. Searching by _id is an extremely frequent operation, so moongose provides a dedicated method for it. Find the (only!!) person having a given _id, using Model.findById() -> Person. Use the function argument personId as search key."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Find an item by Id should succeed",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/find-by-id').then(data => { assert.equal(data.name, 'test', 'item.name is not what expected'); assert.equal(data.age, 0, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['none'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb8367417b2b2512c0e",
- "title": "Perform Classic Updates by Running Find, Edit, then Save",
- "description": [
- "In the good old days this was what you needed to do if you wanted to edit a document and be able to use it somehow e.g. sending it back in a server response. Mongoose has a dedicated updating method : Model.update(). It is binded to the low-level mongo driver. It can bulk edit many documents matching certain criteria, but it doesn’t send back the updated document, only a ‘status’ message. Furthermore it makes model validations difficult, because it just directly calls the mongo driver.",
- "Find a person by _id ( use any of the above methods ) with the parameter personId as search key. Add “hamburger” to the list of her favoriteFoods (you can use Array.push()). Then - inside the find callback - save() the updated Person.",
- "[*] Hint: This may be tricky if in your Schema you declared favoriteFoods as an Array, without specifying the type (i.e. [String]). In that casefavoriteFoods defaults to Mixed type, and you have to manually mark it as edited using document.markModified('edited-field'). (http://mongoosejs.com/docs/schematypes.html - #Mixed )"
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Find-edit-update an item should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-edit-save', {name:'Poldo', age: 40, favoriteFoods:['spaghetti']}).then(data => { assert.equal(data.name, 'Poldo', 'item.name is not what expected'); assert.equal(data.age, 40, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['spaghetti', 'hamburger'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 1, 'The item should be previously edited'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb8367417b2b2512c0f",
- "title": "Perform New Updates on a Document Using model.findOneAndUpdate()",
- "description": [
- "Recent versions of mongoose have methods to simplify documents updating. Some more advanced features (i.e. pre/post hooks, validation) behave differently with this approach, so the Classic method is still useful in many situations. findByIdAndUpdate() can be used when searching by Id.",
- "Find a person by Name and set her age to 20. Use the function parameter personName as search key.",
- "Hint: We want you to return the updated document. o do that you need to pass the options document { new: true } as the 3rd argument to findOneAndUpdate(). By default these methods return the unmodified object."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "findOneAndUpdate an item should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-one-update', {name:'Dorian Gray', age: 35, favoriteFoods:['unknown']}).then(data => { assert.equal(data.name, 'Dorian Gray', 'item.name is not what expected'); assert.equal(data.age, 20, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['unknown'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'findOneAndUpdate does not increment version by design !!!'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb8367417b2b2512c10",
- "title": "Delete One Document Using model.findByIdAndRemove",
- "description": [
- "Delete one person by her _id. You should use one of the methods findByIdAndRemove() or findOneAndRemove(). They are like the previous update methods. They pass the removed document to the cb. As usual, use the function argument personId as search key."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Deleting an item should succeed",
- "testString": "getUserInput => $.post(getUserInput('url') + '/_api/remove-one-person', {name:'Jason Bourne', age: 36, favoriteFoods:['apples']}).then(data => { assert.equal(data.name, 'Jason Bourne', 'item.name is not what expected'); assert.equal(data.age, 36, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['apples'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0); assert.equal(data.count, 0, 'the db items count is not what expected'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb8367417b2b2512c11",
- "title": "Delete Many Documents with model.remove()",
- "description": [
- "Model.remove() is useful to delete all the documents matching given criteria. Delete all the people whose name is “Mary”, using Model.remove(). Pass to it a query ducument with the “name” field set, and of course a callback.",
- "Note: Model.remove() doesn’t return the deleted document, but a JSON object containing the outcome of the operation, and the number of items affected. Don’t forget to pass it to the done() callback, since we use it in tests."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Deleting many items at once should succeed",
- "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/remove-many-people', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'Mary', age: 16, favoriteFoods: ['lollipop']}, {name: 'Mary', age: 21, favoriteFoods: ['steak']}])}).then(data => { assert.isTrue(!!data.ok, 'The mongo stats are not what expected'); assert.equal(data.n, 2, 'The number of items affected is not what expected'); assert.equal(data.count, 0, 'the db items count is not what expected'); }, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "587d7fb9367417b2b2512c12",
- "title": "Chain Search Query Helpers to Narrow Search Results",
- "description": [
- "If you don’t pass the callback as the last argument to Model.find() (or to the other search methods), the query is not executed. You can store the query in a variable for later use. This kind of object enables you to build up a query using chaining syntax. The actual db search is executed when you finally chain the method .exec(). Pass your callback to this last method. There are many query helpers, here we’ll use the most ‘famous’ ones.",
- "Find people who like \"burrito\". Sort them by name, limit the results to two documents, and hide their age. Chain .find(), .sort(), .limit(), .select(), and then .exec(). Pass the done(err, data) callback to exec()."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Chaining query helpers should succeed",
- "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/query-tools', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'Pablo', age: 26, favoriteFoods: ['burrito', 'hot-dog']}, {name: 'Ashley', age: 32, favoriteFoods: ['steak', 'burrito']}, {name: 'Mario', age: 51, favoriteFoods: ['burrito', 'prosciutto']} ]) }).then(data => { assert.isArray(data, 'the response should be an Array'); assert.equal(data.length, 2, 'the data array length is not what expected'); assert.notProperty(data[0], 'age', 'The returned first item has too many properties'); assert.equal(data[0].name, 'Ashley', 'The returned first item name is not what expected'); assert.notProperty(data[1], 'age', 'The returned second item has too many properties'); assert.equal(data[1].name, 'Mario', 'The returned second item name is not what expected');}, xhr => { throw new Error(xhr.responseText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- }
- ]
-}
diff --git a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json b/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json
deleted file mode 100644
index 2b57838734..0000000000
--- a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json
+++ /dev/null
@@ -1,740 +0,0 @@
-{
- "name": "Advanced Node and Express",
- "order": 3,
- "time": "5 hours",
- "helpRoom": "Help",
- "challenges": [
- {
- "id": "5895f6fff9fc0f352b528e62",
- "title": "Advanced Node/Express Introduction",
- "description": [
- "",
- "",
- "Authentication is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.\"pug\": \"^0.1.0\"
",
- "Now to tell Node/Express to use the templating engine you will have to tell your express app to set 'pug' as the 'view-engine'. app.set('view engine', 'pug')
",
- "Lastly, you should change your response to the request for the index route to res.render
with the path to the view views/pug/index.pug.",
- "If all went as planned, you should refresh your apps home page and see a small message saying you're successfully rending the Pug from our Pug file! Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Pug is a dependency",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'pug', 'Your project should list \"pug\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "View engine is Pug",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")view engine('|\"),( |)('|\")pug('|\")/gi, 'Your project should set Pug as a view engine'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Pug is working",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-success-message/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70bf9fc0f352b528e64",
- "title": "Use a Template Engine's Powers",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "One of the greatest features of using a template engine is being able to pass variables from the server to the template file before rendering it to HTML.",
- "In your Pug file, you're about to use a variable by referencing the variable name as #{variable_name}
inline with other text on an element or by using an equal side on the element without a space such as p= variable_name
which sets that p elements text to equal the variable.",
- "We strongly recommend looking at the syntax and structure of Pug here on their Githubs README. Pug is all about using whitespace and tabs to show nested elements and cutting down on the amount of code needed to make a beautiful site.",
- "Looking at our pug file 'index.pug' included in your project, we used the variables title and message",
- "To pass those alone from our server, you will need to add an object as a second argument to your res.render with the variables and their value. For example, pass this object along setting the variables for your index view: {title: 'Hello', message: 'Please login'
",
- "It should look like: res.render(process.cwd() + '/views/pug/index', {title: 'Hello', message: 'Please login'});
",
- "Now refresh your page and you should see those values rendered in your view in the correct spot as layed out in your index.pug file! Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Pug render variables correct",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-variable(\"|')>Please login/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70cf9fc0f352b528e65",
- "title": "Set up Passport",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "It's time to set up Passport so we can finally start allowing a user to register or login to an account! In addition to Passport, we will use Express-session to handle sessions. Using this middleware saves the session id as a cookie in the client and allows us to access the session data using that id on the server. This way we keep personal account information out of the cookie used by the client to verify to our server they are authenticated and just keep the key to access the data stored on the server.",
- "To set up Passport for use in your project, you will need to add it as a dependency first in your package.json. \"passport\": \"^0.3.2\"
",
- "In addition, add Express-session as a dependency now as well. Express-session has a ton of advanced features you can use but for now we're just going to use the basics! \"express-session\": \"^1.15.0\"
",
- "You will need to set up the session settings now and initialize Passport. Be sure to first create the variables 'session' and 'passport' to require 'express-session' and 'passport' respectively.",
- "To set up your express app to use use the session we'll define just a few basic options. Be sure to add 'SESSION_SECRET' to your .env file and give it a random value. This is used to compute the hash used to encrypt your cookie!",
- "app.use(session({\n secret: process.env.SESSION_SECRET,\n resave: true,\n saveUninitialized: true,\n}));", - "As well you can go ahead and tell your express app to use 'passport.initialize()' and 'passport.session()'. (For example,
app.use(passport.initialize());
)",
- "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Passort and Express-session are dependencies",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport', 'Your project should list \"passport\" as a dependency'); assert.property(packJson.dependencies, 'express-session', 'Your project should list \"express-session\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Dependencies correctly required",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport(\"|')/gi, 'You should have required passport'); assert.match(data, /require.*(\"|')express-session(\"|')/gi, 'You should have required express-session'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Express app uses new dependencies",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.initialize/gi, 'Your express app should use \"passport.initialize()\"'); assert.match(data, /passport.session/gi, 'Your express app should use \"passport.session()\"'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Session and session secret correctly set up",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /secret:( |)process.env.SESSION_SECRET/gi, 'Your express app should have express-session set up with your secret as process.env.SESSION_SECRET'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70cf9fc0f352b528e66",
- "title": "Serialization of a User Object",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Serialization and deserialization are important concepts in regards to authentication. To serialize an object means to convert its contents into a small key essentially that can then be deserialized into the original object. This is what allows us to know whos communicated with the server without having to send the authentication data like username and password at each request for a new page.",
- "To set this up properly, we need to have a serialize function and a deserialize function. In passport we create these with passport.serializeUser( OURFUNCTION )
and passport.deserializeUser( OURFUNCTION )
",
- "The serializeUser is called with 2 arguments, the full user object and a callback used by passport. Returned in the callback should be a unique key to identify that user- the easiest one to use being the users _id in the object as it should be unique as it generated by MongoDb. Similarly deserializeUser is called with that key and a callback function for passport as well, but this time we have to take that key and return the users full object to the callback. To make a query search for a Mongo _id you will have to create const ObjectID = require('mongodb').ObjectID;
, and then to use it you call new ObjectID(THE_ID)
. Be sure to add MongoDB as a dependency. You can see this in the examples below:",
- "passport.serializeUser((user, done) => {\n done(null, user._id);\n });
passport.deserializeUser((id, done) => {\n db.collection('users').findOne(\n {_id: new ObjectID(id)},\n (err, doc) => {\n done(null, doc);\n }\n );\n });", - "NOTE: This deserializeUser will throw an error until we set up the DB in the next step so comment out the whole block and just call
done(null, null)
in the function deserializeUser.",
- "Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Serialize user function correct",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.serializeUser/gi, 'You should have created your passport.serializeUser function'); assert.match(data, /null, user._id/gi, 'There should be a callback in your serializeUser with (null, user._id)'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Deserialize user function correct",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.deserializeUser/gi, 'You should have created your passport.deserializeUser function'); assert.match(data, /null,( |)null/gi, 'There should be a callback in your deserializeUser with (null, null) for now'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "MongoDB is a dependency",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'mongodb', 'Your project should list \"mongodb\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Mongodb properly required including the ObjectId",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')mongodb(\"|')/gi, 'You should have required mongodb'); assert.match(data, /new ObjectID.*id/gi, 'Even though the block is commented out, you should use new ObjectID(id) for when we add the database'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70cf9fc0f352b528e67",
- "title": "Implement the Serialization of a Passport User",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Right now we're not loading an actually users object since we haven't set up our database. This can be done many different ways, but for our project we will connect to the database once when we start the server and keep a persistent connection for the full life-cycle of the app.",
- "To do this, add MongoDB as a dependency and require it in your server. (const mongo = require('mongodb').MongoClient;
)",
- "Now we want to the connect to our database then start listening for requests. The purpose of this is to not allow requests before our database is connected or if there is a database error. To accomplish you will want to encompass your serialization and your app listener in the following:",
- "mongo.connect(process.env.DATABASE, (err, db) => {\n if(err) {\n console.log('Database error: ' + err);\n } else {\n console.log('Successful database connection');\n\n //serialization and app.listen\n\n}});", - "You can now uncomment the block in deserializeUser and remove your
done(null, null)
. Be sure to set DATABASE in your .env file to your database's connection string (for example: DATABASE=mongodb://admin:pass@mlab.com:12345/my-project
). You can set up a free database on mLab. Congratulations- you've finished setting up serialization!",
- "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Database connection is present",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /mongo.connect/gi, 'You should have created a connection to your database'); assert.match(data, /mongo.connect[^]*app.listen[^]*}[^]*}/gi, 'You should have your app.listen nested at within your database connection at the bottom'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Deserialization is now correctly using the DB and done(null, null)
is erased",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.notMatch(data, /null,( |)null/gi, 'The callback in deserializeUser of (null, null) should be completely removed for the db block uncommented out'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70df9fc0f352b528e68",
- "title": "Authentication Strategies",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "A strategy is a way of authenticating a user. You can use a strategy for allowing users to authenticate based on locally saved information (if you have them register first) or from a variety of providers such as Google or Github. For this project we will set up a local strategy. To see a list of the 100's of strategies, visit Passports site here.",
- "Add passport-local as a dependency and add it to your server as follows: const LocalStrategy = require('passport-local');
",
- "Now you will have to tell passport to use an instantiated LocalStartegy object with a few settings defined. Make sure this as well as everything from this point on is encapsulated in the database connection since it relies on it! passport.use(new LocalStrategy(\n function(username, password, done) {\n db.collection('users').findOne({ username: username }, function (err, user) {\n console.log('User '+ username +' attempted to log in.');\n if (err) { return done(err); }\n if (!user) { return done(null, false); }\n if (password !== user.password) { return done(null, false); }\n return done(null, user);\n });\n }\n));This is defining the process to take when we try to authenticate someone locally. First it tries to find a user in our database with the username entered, then it checks for the password to match, then finally if no errors have popped up that we checked for, like an incorrect password, the users object is returned and they are authenticated.", - "Many strategies are set up using different settings, general it is easy to set it up based on the README in that strategies repository though. A good example of this is the Github strategy where we don't need to worry about a username or password because the user will be sent to Github's auth page to authenticate and as long as they are logged in and agree then Github returns their profile for us to use.", - "In the next step we will set up how to actually call the authentication strategy to validate a user based on form data! Submit your page when you think you've got it right up to this point." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Passport-local is a dependency", - "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-local', 'Your project should list \"passport-local \" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Passport-local correctly required and setup", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport-local(\"|')/gi, 'You should have required passport-local'); assert.match(data, /new LocalStrategy/gi, 'You should have told passport to use a new strategy'); assert.match(data, /findOne/gi, 'Your new local strategy should use the findOne query to find a username based on the inputs'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70df9fc0f352b528e69", - "title": "How to Use Passport Strategies", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "In the index.pug file supplied there is actually a login form. It has previously been hidden because of the inline javascript
if showLogin
with the form indented after it. Before showLogin as a variable was never defined, it never rendered the code block containing the form. Go ahead and on the res.render for that page add a new variable to the object showLogin: true
. When you refresh your page, you should then see the form! This form is set up to POST on /login so this is where we should set up to accept the POST and authenticate the user.",
- "For this challenge you should add the route /login to accept a POST request. To authenticate on this route you need to add a middleware to do so before then sending a response. This is done by just passing another argument with the middleware before your function(req,res)
with your response! The middleware to use is passport.authenticate('local')
.",
- "passport.authenticate can also take some options as an argument such as: { failureRedirect: '/' }
which is incredibly useful so be sure to add that in as well. As a response after using the middleware (which will only be called if the authentication middleware passes) should be to redirect the user to /profile and that route should render the view 'profile.pug'.",
- "If the authentication was successful, the user object will be saved in req.user.",
- "Now at this point if you enter a username and password in the form, it should redirect to the home page / and in the console of your server should be 'User {USERNAME} attempted to log in.' since we currently cannot login a user who isn't registered.",
- "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "All steps correctly implemented in the server.js",
- "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showLogin:( |)true/gi, 'You should be passing the variable \"showLogin\" as true to your render function for the homepage'); assert.match(data, /failureRedirect:( |)('|\")\\/('|\")/gi, 'Your code should include a failureRedirect to the \"/\" route'); assert.match(data, /login[^]*post[^]*local/gi, 'You should have a route for login which accepts a POST and passport.authenticates local'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "A POST request to /login correctly redirects to /",
- "testString": "getUserInput => $.post(getUserInput('url')+ '/login') .then(data => { assert.match(data, /Home page/gi, 'A login attempt at this point should redirect to the homepage since we do not have any registered users'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "5895f70df9fc0f352b528e6a",
- "title": "Create New Middleware",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "As in, any user can just go to /profile whether they authenticated or not by typing in the url. We want to prevent this by checking if the user is authenticated first before rendering the profile page. This is the perfect example of when to create a middleware.",
- "The challenge here is creating the middleware function ensureAuthenticated(req, res, next)
, which will check if a user is authenticated by calling passports isAuthenticated on the request which in turn checks for req.user is to be defined. If it is then next() should be called, otherwise we can just respond to the request with a redirect to our homepage to login. An implementation of this middleware is:",
- "function ensureAuthenticated(req, res, next) {\n if (req.isAuthenticated()) {\n return next();\n }\n res.redirect('/');\n};", - "Now add ensureAuthenticated as a middleware to the request for the profile page before the argument to the get request containing the function that renders the page.", - "
app.route('/profile')\n .get(ensureAuthenticated, (req,res) => {\n res.render(process.cwd() + '/views/pug/profile');\n });", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Middleware ensureAuthenticated should be implemented and on our /profile route", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /ensureAuthenticated[^]*req.isAuthenticated/gi, 'Your ensureAuthenticated middleware should be defined and utilize the req.isAuthenticated function'); assert.match(data, /profile[^]*get[^]*ensureAuthenticated/gi, 'Your ensureAuthenticated middleware should be attached to the /profile route'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "A Get request to /profile correctly redirects to / since we are not authenticated", - "testString": "getUserInput => $.get(getUserInput('url')+ '/profile') .then(data => { assert.match(data, /Home page/gi, 'An attempt to go to the profile at this point should redirect to the homepage since we are not logged in'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70ef9fc0f352b528e6b", - "title": "How to Put a Profile Together", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Now that we can ensure the user accessing the /profile is authenticated, we can use the information contained in 'req.user' on our page!", - "Go ahead and pass the object containing the variable username equaling 'req.user.username' into the render method of the profile view. Then go to your 'profile.pug' view and add the line
h2.center#welcome Welcome, #{username}!
creating the h2 element with the class 'center' and id 'welcome' containing the text 'Welcome, ' and the username!",
- "Also in the profile, add a link to /logout. That route will host the logic to unauthenticate a user. a(href='/logout') Logout
",
- "Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Correctly added a Pug render variable to /profile",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /\\/views\\/pug\\/profile[^]*username:( |)req.user.username/gi, 'You should be passing the variable username with req.user.username into the render function of the profile page'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "58965611f9fc0f352b528e6c",
- "title": "Logging a User Out",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Creating the logout logic is easy. The route should just unauthenticate the user and redirect to the home page instead of rendering any view.",
- "In passport, unauthenticating a user is as easy as just calling req.logout();
before redirecting.",
- "app.route('/logout')\n .get((req, res) => {\n req.logout();\n res.redirect('/');\n });", - "You may have noticed we also we're not handling missing pages (404), the common way to handle this in Node is with the following middleware. Go ahead and add this in after all your other routes:", - "
app.use((req, res, next) => {\n res.status(404)\n .type('text')\n .send('Not Found');\n});", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Logout route", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /req.logout/gi, 'You should be call req.logout() in youre /logout route'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Logout should redirect to the home page /", - "testString": "getUserInput => $.get(getUserInput('url')+ '/logout') .then(data => { assert.match(data, /Home page/gi, 'When a user logs out they should be redirected to the homepage'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58966a17f9fc0f352b528e6d", - "title": "Registration of New Users", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along-
showRegistration: true
. When you refresh your page, you should then see the registration form that was already created in your index.pug file! This form is set up to POST on /register so this is where we should set up to accept the POST and create the user object in the database.",
- "The logic of the registration route should be as follows: Register the new user > Authenticate the new user > Redirect to /profile",
- "The logic of step 1, registering the new user, should be as follows: Query database with a findOne command > if user is returned then it exists and redirect back to home OR if user is undefined and no error occurs then 'insertOne' into the database with the username and password and as long as no errors occur then call next to go to step 2, authenticating the new user, which we've already written the logic for in our POST /login route.",
- "app.route('/register')\n .post((req, res, next) => {\n db.collection('users').findOne({ username: req.body.username }, function (err, user) {\n if(err) {\n next(err);\n } else if (user) {\n res.redirect('/');\n } else {\n db.collection('users').insertOne(\n {username: req.body.username,\n password: req.body.password},\n (err, doc) => {\n if(err) {\n res.redirect('/');\n } else {\n next(null, user);\n }\n }\n )\n }\n })},\n passport.authenticate('local', { failureRedirect: '/' }),\n (req, res, next) => {\n res.redirect('/profile');\n }\n);", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Register route and display on home", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showRegistration:( |)true/gi, 'You should be passing the variable \"showRegistration\" as true to your render function for the homepage'); assert.match(data, /register[^]*post[^]*findOne[^]*username:( |)req.body.username/gi, 'You should have a route accepted a post request on register that querys the db with findone and the query being \"username: req.body.username\"'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Registering should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/register',data: {username: 'freeCodeCampTester', password: 'freeCodeCampTester'},crossDomain: true, type: 'POST', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, 'I should be able to register and it direct me to my profile. CLEAR YOUR DATABASE if this test fails (each time until its right!)'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Login should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/login',data: {username: 'freeCodeCampTester', password: 'freeCodeCampTester'}, type: 'POST', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, 'Login should work if previous test was done successfully and redirect successfully to the profile. Check your work and clear your DB'); assert.match(data, /freeCodeCampTester/gi, 'The profile should properly display the welcome to the user logged in'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Logout should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/logout', type: 'GET', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Logout should redirect to home'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Profile should no longer work after logout", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/profile', type: 'GET', crossDomain: true, xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Profile should redirect to home when we are logged out now again'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58a25c98f9fc0f352b528e7f", - "title": "Hashing Your Passwords", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Going back to the information security section you may remember that storing plaintext passwords is never okay. Now it is time to implement BCrypt to solve this issue.", - "
password: req.body.password
. An easy way to implement saving a hash instead is to add the following before your database logic var hash = bcrypt.hash(req.body.password, 12);
and replacing the req.body.password
in the database saving with just password: hash
.",
- "Finally on our authentication strategy we check for the following in our code before completing the process: if (password !== user.password) { return done(null, false); }
. After making the previous changes, now user.password
is a hash. Before making a change to the existing code, notice how the statement is checking if the password is NOT equal then return non-authenticated. With this in mind your code could look as follows to properly check the password entered against the hash: if (!bcrypt.compare(password, user.password)) { return done(null, false); }
",
- "That is all it takes to implement one of the most important security features when you have to store passwords! Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "BCrypt is a dependency",
- "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'bcrypt', 'Your project should list \"bcrypt\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "BCrypt correctly required and implemented",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')bcrypt(\"|')/gi, 'You should have required bcrypt'); assert.match(data, /bcrypt.hash/gi, 'You should use hash the password in the registration'); assert.match(data, /bcrypt.compare/gi, 'You should compare the password to the hash in your strategy'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "589690e6f9fc0f352b528e6e",
- "title": "Clean Up Your Project with Modules",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Right now everything you have is in your server.js file. This can lead to hard to manage code that isn't very expandable.",
- "Create 2 new files: Routes.js and Auth.js",
- "Both should start with the following code: module.exports = function (app, db) {\n\n\n}", - "Now in the top of your server file, require these files like such:
const routes = require('./routes.js');
",
- "Right after you establish a successful connect with the database instantiate each of them like such: routes(app, db)
",
- "Finally, take all of the routes in your server and paste them into your new files and remove them from your server file. Also take the ensureAuthenticated since we created that middleware function for routing specifically. You will have to now correctly add the dependencies in that are used, such as const passport = require('passport');
, at the very top above the export line in your routes.js file.",
- "Keep adding them until no more errors exist, and your server file no longer has any routing!",
- "Now do the same thing in your auth.js file with all of the things related to authentication such as the serialization and the setting up of the local strategy and erase them from your server file. Be sure to add the dependencies in and call auth(app,db)
in the server in the same spot. Be sure to have auth(app, db)
before routes(app, db)
since our registration route depends on passport being initiated!",
- "Congratulations- you're at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project here."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Modules present",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|').\\/routes.js(\"|')/gi, 'You should have required your new files'); assert.match(data, /mongo.connect[^]*routes/gi, 'Your new modules should be called after your connection to the database'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "589a69f5f9fc0f352b528e6f",
- "title": "Social Authentication with OAuth",
- "description": [
- [
- "",
- "",
- "OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.passport.authenticate('github')
which redirects them to Github.process.env.GITHUB_CLIENT_ID
. For this challenge we're going to use the Github strategy.",
- "Obtaining your Client ID and Secret from Github is done in your account profile settings under 'developer settings', then 'OAuth applications'. Click 'Register a new application', name your app, paste in the url to your glitch homepage (Not the project code's url), and lastly for the callback url, paste in the same url as the homepage but with '/auth/github/callback' added on. This is where users will be redirected to for us to handle after authenticating on Github. Save the returned information as 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' in your .env file.",
- "On your remixed project, create 2 routes accepting GET requests: /auth/github and /auth/github/callback. The first should only call passport to authenticate 'github' and the second should call passport to authenticate 'github' with a failure redirect to '/' and then if that is successful redirect to '/profile' (similar to our last project).",
- "An example of how '/auth/github/callback' should look is similar to how we handled a normal login in our last project: app.route('/login')\n .post(passport.authenticate('local', { failureRedirect: '/' }), (req,res) => { \n res.redirect('/profile'); \n });", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Route /auth/github correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")\\/auth\\/github('|\")[^]*get.*passport.authenticate.*github/gi, 'Route auth/github should only call passport.authenticate with github'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Route /auth/github/callback correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")\\/auth\\/github\\/callback('|\")[^]*get.*passport.authenticate.*github.*failureRedirect:( |)(\"|')\\/(\"|')/gi, 'Route auth/github/callback should accept a get request and call passport.authenticate for github with a failure redirect to home'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589a69f5f9fc0f352b528e71", - "title": "Implementation of Social Authentication II", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "The last part of setting up your Github authentication is to create the strategy itself. For this, you will need to add the dependency of 'passport-github' to your project and require it as GithubStrategy like
const GitHubStrategy = require('passport-github').Strategy;
.",
- "To set up the Github strategy, you have to tell passport to use an instantiated GithubStrategy, which accepts 2 arguments: An object (containing clientID, clientSecret, and callbackURL) and a function to be called when a user is successfully authenticated which we will determine if the user is new and what fields to save initially in the user's database object. This is common across many strategies but some may require more information as outlined in that specific strategy's github README; for example, Google requires a scope as well which determines what kind of information your request is asking returned and asks the user to approve such access. The current strategy we are implementing has its usage outlined here, but we're going through it all right here on freeCodeCamp!",
- "Here's how your new strategy should look at this point: passport.use(new GitHubStrategy({\n clientID: process.env.GITHUB_CLIENT_ID,\n clientSecret: process.env.GITHUB_CLIENT_SECRET,\n callbackURL: /*INSERT CALLBACK URL ENTERED INTO GITHUB HERE*/\n },\n function(accessToken, refreshToken, profile, cb) {\n console.log(profile);\n //Database logic here with callback containing our user object\n }\n));", - "Your authentication won't be successful yet, and actually throw an error, without the database logic and callback, but it should log to your console your Github profile if you try it!", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Dependency added", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-github', 'Your project should list \"passport-github\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Dependency required", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport-github(\"|')/gi, 'You should have required passport-github'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Github strategy setup correctly thus far", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.use.*new GitHubStrategy/gi, 'Passport should use a new GitHubStrategy'); assert.match(data, /callbackURL:( |)(\"|').*(\"|')/gi, 'You should have a callbackURL'); assert.match(data, /process.env.GITHUB_CLIENT_SECRET/g, 'You should use process.env.GITHUB_CLIENT_SECRET'); assert.match(data, /process.env.GITHUB_CLIENT_ID/g, 'You should use process.env.GITHUB_CLIENT_ID'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589a8eb3f9fc0f352b528e72", - "title": "Implementation of Social Authentication III", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "The final part of the strategy is handling the profile returned from Github. We need to load the users database object if it exists or create one if it doesn't and populate the fields from the profile, then return the user's object. Github supplies us a unique id within each profile which we can use to search with to serialize the user with (already implemented). Below is an example implementation you can use in your project- it goes within the function that is the second argument for the new strategy, right below the
console.log(profile);
currently is:",
- "db.collection('socialusers').findAndModify(\n {id: profile.id},\n {},\n {$setOnInsert:{\n id: profile.id,\n name: profile.displayName || 'John Doe',\n photo: profile.photos[0].value || '',\n email: profile.emails[0].value || 'No public email',\n created_on: new Date(),\n provider: profile.provider || ''\n },$set:{\n last_login: new Date()\n },$inc:{\n login_count: 1\n }},\n {upsert:true, new: true},\n (err, doc) => {\n return cb(null, doc.value);\n }\n);", - "With a findAndModify, it allows you to search for an object and update it, as well as upsert the object if it doesn't exist and receive the new object back each time in our callback function. In this example, we always set the last_login as now, we always increment the login_count by 1, and only when we insert a new object(new user) do we populate the majority of the fields. Something to notice also is the use of default values. Sometimes a profile returned won't have all the information filled out or it will have been chosen by the user to remain private; so in this case we have to handle it to prevent an error.", - "You should be able to login to your app now- try it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of this mini-project's finished code here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Github strategy setup complete", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /GitHubStrategy[^]*db.collection/gi, 'Strategy should use now use the database to search for the user'); assert.match(data, /GitHubStrategy[^]*socialusers/gi, 'Strategy should use \"socialusers\" as db collection'); assert.match(data, /GitHubStrategy[^]*return cb/gi, 'Strategy should return the callback function \"cb\"'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc820f9fc0f352b528e73", - "title": "Socket.IO Introduction", - "description": [ - [ - "", - "", - "Socket.IO enables real-time, reliable, speedy communication between your server and clients from all devices and browsers. It listens for connects on your server that come from the client which connects with a single javascript statement. The whole library is based on emitting, broadcasting, and recieving events that contain an event name and some data which can include things like strings, objects, arrays, and even blobs like files or video. This is used for all sorts of purposes including instant messaging online, real-time analytics, streaming, and document collaboration.
app.listen
, you now have const http = require('http').Server(app);\n\nhttp.listen(process.env.PORT || 3000);This is required because for the initial handshake between the server and client, http is used. Setting up our server like this allows us to have both processes use a single port.
const sessionStore = new session.MemoryStore();
and used sessionStore
as the store in our express session. In our previous apps we have not done this because by default it is done automattically. It is not this way so we can reference/use the sessionStore
in other parts of our code now. In addition, we've given our session a key to reference it easier.",
- ""
- ]
- ],
- "releasedOn": "Feb 17, 2017",
- "challengeSeed": [],
- "tests": [],
- "type": "waypoint",
- "challengeType": 7,
- "isRequired": false
- },
- {
- "id": "589fc830f9fc0f352b528e74",
- "title": "Set up the Enviroment",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Add Socket.IO as a dependency and require/instanciate it in your server defined as 'io' with the http server as an argument. const io = require('socket.io')(http);
",
- "The first thing needing to be handled is listening for a new connection from the client. The on keyword does just that- listen for a specific event. It requires 2 arguments: a string containing the title of the event thats emitted, and a function with which the data is passed though. In the case of our connection listener, we use socket to define the data in the second argument. A socket is an individual client who is connected.",
- "For listening for connections on our server, add the following between the comments in your project:io.on('connection', socket => {\n console.log('A user has connected');\n});", - "Now for the client to connect, you just need to add the following to your client.js which is loaded by the page after you've authenticated:
/*global io*/\nvar socket = io();The comment supresses the error you would normally see since 'io' is not defined in the file. We've already added a reliable CDN to the Socket.IO library on the page in chat.pug.", - "Now try loading up your app and authenticate and you should see in your server console 'A user has connected'!", - "Note
io()
works only when connecting to a socket hosted on the same url/server. For connecting to an external socket hosted elsewhere, you would use io.connect('URL');
.",
- "Submit your page when you think you've got it right."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Socket.IO is a dependency",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'socket.io', 'Your project should list \"socket.io\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Socket.IO has been properly required and instanciated",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /io.*=.*require.*('|\")socket.io('|\").*http/gi, 'You should correctly require and instanciate socket.io as io.');}, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Socket.IO should be listening for connections",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.on.*('|\")connection('|\").*socket/gi, 'io should listen for \"connection\" and socket should be the 2nd arguments variable'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Your client should connect to your server",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.*=.*io/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "589fc831f9fc0f352b528e75",
- "title": "Communicate by Emitting",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Emit is the most common way of communicating you will use. When you emit something from the server to 'io', you send an event's name and data to all the connected sockets. A good example of this concept would be emiting the current count of connected users each time a new user connects!",
- "var currentUsers = 0;
",
- "Now when someone connects you should increment the count before emiting the count so you will want to add the incrementer within the connection listener. ++currentUsers;
",
- "Finally after incrementing the count, you should emit the event(still within the connection listener). The event should be named 'user count' and the data should just be the 'currentUsers'. io.emit('user count', currentUsers);
",
- "socket.on('user count', function(data){\n console.log(data);\n});", - "Now try loading up your app and authenticate and you should see in your client console '1' representing the current user count! Try loading more clients up and authenticating to see the number go up.", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "currentUsers is defined", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /currentUsers/gi, 'You should have variable currentUsers defined');}, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Server emits the current user count at each new connection", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|\")user count('|\").*currentUsers/gi, 'You should emit \"user count\" with data currentUsers'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Your client is listening for 'user count' event", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user count('|\")/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc831f9fc0f352b528e76", - "title": "Handle a Disconnect", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "You may notice that up to now you have only been increasing the user count. Handling a user disconnecting is just as easy as handling the initial connect except the difference is you have to listen for it on each socket versus on the whole server.", - "
socket.on('disconnect', () => { /*anything you want to do on disconnect*/ });
",
- "To make sure clients continuously have the updated count of current users, you should decrease the currentUsers by 1 when the disconnect happens then emit the 'user count' event with the updated count!",
- "Noteio.use(passportSocketIo.authorize({\n cookieParser: cookieParser,\n key: 'express.sid',\n secret: process.env.SESSION_SECRET,\n store: sessionStore\n}));You can also optionally pass 'success' and 'fail' with a function that will be called after the authentication process completes when a client trys to connect.", - "The user object is now accessable on your socket object as
socket.request.user
. For example, now you can add the following: console.log('user ' + socket.request.user.name + ' connected');
and it will log to the server console who has connected!",
- "Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "passportSocketIo is a dependency",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passportSocketIo', 'Your project should list \"passportSocketIo\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "passportSocketIo is properly required",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /passportSockerIo.*=.*require.*('|\")passportSocketIo('|\")/gi, 'You should correctly require and instanciate socket.io as io.');}, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "passportSocketIo is properly setup",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.use.*passportSocketIo.authorize/gi, 'You should have told io to use passportSockIo.authorize with the correct options'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "589fc832f9fc0f352b528e78",
- "title": "Announce New Users",
- "description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Many chat rooms are able to annouce when a user connects or disconnects and then display that to all of the connected users in the chat. Seeing as though you already are emitting an event on connect and disconnect, you will just have to modify this event to support such feature. The most logical way of doing so is sending 3 pieces of data with the event: name of the user connected/disconnected, the current user count, and if that name connected or disconnected.",
- "io.emit('user', {name: socket.request.user.name, currentUsers, connected: true});
",
- "Now your client will have all the nesesary information to correctly display the current user count and annouce when a user connects or disconnects! To handle this event on the client side we should listen for 'user' and then update the current user count by using jQuery to change the text of #num-users
to '{NUMBER} users online', as well as append a <li>
to the unordered list with id 'messages' with '{NAME} has {joined/left} the chat.'.",
- "An implementation of this could look like the following:socket.on('user', function(data){\n $('#num-users').text(data.currentUsers+' users online');\n var message = data.name;\n if(data.connected) {\n message += ' has joined the chat.';\n } else {\n message += ' has left the chat.';\n }\n $('#messages').append($('<li>').html('<b>'+ message +'<\\/b>'));\n});", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Event 'user' is emitted with name, currentUsers, and connected", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|\")user('|\").*name.*currentUsers.*connected/gi, 'You should have an event emitted named user sending name, currentUsers, and connected'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Client properly handling and displaying the new data from event 'user'", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user('|\")[^]*num-users/gi, 'You should change the text of #num-users within on your client within the \"user\" even listener to show the current users connected'); assert.match(data, /socket.on.*('|\")user('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"user\" event listener to annouce a user came or went'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc832f9fc0f352b528e79", - "title": "Send and Display Chat Messages", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "It's time you start allowing clients to send a chat message to the server to emit to all the clients! Already in your client.js file you should see there is already a block of code handling when the messgae form is submitted! (
$('form').submit(function(){ /*logic*/ });
)",
- "#m
. The event should be named 'chat message' and the data should just be 'messageToSend'. socket.emit('chat message', messageToSend);
",
- "Now on your server you should be listening to the socket for the event 'chat message' with the data being named 'message'. Once the event is recieved it should then emit the event 'chat message' to all sockets io.emit
with the data being an object containing 'name' and 'message'.",
- "On your client now again, you should now listen for event 'chat message' and when recieved, append a list item to #messages
with the name a colon and the message!",
- "At this point the chat should be fully functional and sending messages across all clients! Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here for the server and here for the client."
- ],
- "challengeSeed": [],
- "tests": [
- {
- "text": "Server listens for 'chat message' then emits it properly",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /socket.on.*('|\")chat message('|\")[^]*io.emit.*('|\")chat message('|\").*name.*message/gi, 'Your server should listen to the socket for \"chat message\" then emit to all users \"chat message\" with name and message in the data object'); }, xhr => { throw new Error(xhr.statusText); })"
- },
- {
- "text": "Client properly handling and displaying the new data from event 'chat message'",
- "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")chat message('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"chat message\" event listener to display the new message'); }, xhr => { throw new Error(xhr.statusText); })"
- }
- ],
- "solutions": [],
- "hints": [],
- "challengeType": 2,
- "translations": {}
- },
- {
- "id": "58a0b2caf9fc0f352b528e7a",
- "title": "Continuing Your Live Chat",
- "description": [
- [
- "",
- "",
- "From this point, you could choose to implement a plethora of features with just the knowledge you have learned up to this point! Some ideas you could choose to continue this project on with include, but aren't limited to the following: