├── arrays-objetos-metodos ├── .gitignore ├── exercicios-obj.js ├── exercicios-array.js ├── exercicios-extra.js ├── exercicios-extra-resolvidos.js ├── exercicios-array-resolvidos.js ├── exercicios-obj-resolvidos.js ├── exemplos.js └── readme.md ├── funcoes-escopo-loops ├── .gitignore ├── exercicios-extra.js ├── exemplos.js ├── exercicios-extra-resolvidos.js ├── exercicios-funcoes.js ├── exercicios-for.js ├── exercicios-for-resolvidos.js ├── exercicios-funcoes-resolvidos.js └── readme.md ├── README.md └── package.json /arrays-objetos-metodos/.gitignore: -------------------------------------------------------------------------------- 1 | exercicios-array-corrigidos.js 2 | exercicios-obj-corrigidos.js 3 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | exercicios-funcoes-corrigidos.js 3 | exercicios-for-corrigidos.js 4 | exercicios-semana-resolvidos.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tópicos iniciais de JavaScript 2 | 3 | Este material foi desenvolvido para duas aulas de lógica de programação do curso online de backend da {reprograma}, em agosto de 2020. 4 | 5 | O conteúdo foi desenvolvido em grande parte com ajuda do [MDN](https://developer.mozilla.org/en-US/), alguns exemplos e exercícios retirados de partes diversas da ~internet. 6 | 7 | Deixo livre para vocês ;) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logica-js", 3 | "version": "1.0.0", 4 | "description": "Alguns tópicos iniciais de lógica de programação com JS e exercícios", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/JulianaAmoasei/logica-js.git" 11 | }, 12 | "keywords": [], 13 | "author": "https://github.com/JulianaAmoasei", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/JulianaAmoasei/logica-js/issues" 17 | }, 18 | "homepage": "", 19 | "dependencies": { 20 | "readline-sync": "^1.4.10" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-extra.js: -------------------------------------------------------------------------------- 1 | // 1) Calcule a potência de 2 elevado a um número específico. Deve usar um loop (não usar `Math.pow()`). 2 | // Exemplo: 3 | // potenciaDeDois(10) // 1024 4 | 5 | 6 | // 2) Crie uma função que receba três números e determine se um número é maior que outro. 7 | // Exemplo: 8 | // retornaNumMaior(10, 20, 30) // 30 9 | 10 | 11 | // *************** 12 | 13 | // DESAFIOS! 14 | 15 | // Crie uma função que determina se um número é primo e retorne true ou false conforme o caso. Em matemática, um número primo é um número natural maior que 1 que é divisível somente por ele mesmo e 1. Utilize o operador módulo (`%`) para determinar se um número é divisível por outro. 16 | 17 | 18 | // Crie uma função que conte o número de vogais em uma `string` e retorne o número de vogais. 19 | // Exemplo: 20 | // function contaVogais("carro") // 2 21 | 22 | 23 | // Use estruturas de controle para inverter uma array de inteiros. A função deverá receber uma array de números e retornar uma array com a ordem dos elementos invertida. Não é válido utilizar `arr.reverse()`. 24 | // Exemplo: 25 | // function inverteArray([1, 2, 3, 4]) // [4, 3, 2, 1] 26 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-obj.js: -------------------------------------------------------------------------------- 1 | // 1) Crie uma função que receba 3 parâmetros: o nome de um livro, a quantidade de páginas e a autoria. Retorne um objeto no formato: {titulo: "nome do livro", paginas: "número de páginas", autoria: "nome da pessoa"} 2 | 3 | // Exemplo: 4 | // objLivro('Antes do Baile Verde', 234, 'Lygia Fagundes Telles') 5 | 6 | // retorna o objeto: 7 | // { 8 | // titulo: 'Antes do Baile Verde', 9 | // paginas: 234, 10 | // autoria: 'Lygia Fagundes Telles' 11 | // } 12 | 13 | 14 | // 2) Aproveite a função acima em outra função, que deve retornar a seguinte frase: "O livro XXXX foi escrito por XXX e tem XXX páginas". Você deve utilizar a função que já está pronta, e não reescrever a lógica dela dentro dessa nova função. 15 | 16 | 17 | // 3) Crie uma função que receba um objeto como o abaixo: 18 | 19 | // const pessoa = { 20 | // nome: 'Nazaré', 21 | // sobrenome: 'Tedesco', 22 | // } 23 | 24 | // Dado um objeto que tem uma propriedade 'nome' e uma propriedade 'sobrenome', a função deve retornar um novo objeto com as mesmas propriedades que o objeto recebido e mais uma propriedade, chamada 'nomeCompleto', cujo valor é uma string com o nome e sobrenome separados por um espaço. 25 | 26 | // Exemplo de retorno: 27 | // { 28 | // nome: 'Nazaré', 29 | // sobrenome: 'Tedesco', 30 | // nomeCompleto: 'Nazaré Tedesco' 31 | // } 32 | 33 | 34 | // 4) Crie uma função que receba o objeto abaixo e o nome de uma das chaves, e retorne a soma de todos os elementos do array que for selecionado através da chave. 35 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-array.js: -------------------------------------------------------------------------------- 1 | // Exercícios práticos com for e arrays! 2 | 3 | // 1) Crie uma função que receba uma array e imprima no console o número do índice e o elemento. 4 | // Exemplo: recebendo ["banana", "gatinho", "brócolis"] deve imprimir no console: 5 | // índice 0, elemento "banana" 6 | // índice 1, elemento "gatinho" 7 | // índice 2, elemento "brócolis" 8 | 9 | 10 | // 2) Crie uma função que receba uma array de números inteiros e retorne a soma dos elementos. 11 | // Exemplo: recebendo [10,11,12] deve retornar 33 12 | 13 | 14 | // 3) Crie uma função que receba uma array de números inteiros e retorne outra array somente com os elementos maiores que 5. 15 | // Exemplo, recebendo [88,55,0,2,85,81,24,12] deve retornar [ 88, 55, 85, 81, 24, 12 ] 16 | 17 | 18 | // 4) Modifique a função anterior para que receba, além da array, o número para comparação (não deixar mais fixo como número 5). 19 | // Exemplo, recebendo ([88,55,0,2,85,81,24,12], 20) deve retornar [ 88, 55, 85, 81, 24 ] 20 | 21 | 22 | // 5) Crie uma função que receba uma array de números inteiros e retorne o maior número encontrado. 23 | // Exemplo: recebendo [56, 12, 168, 66] deve retornar 168 24 | // EXTRA: Pesquisar uma maneira iniciar com o menor número possível (dica: não é zero) 25 | 26 | 27 | // 6) Crie uma função que receba uma array de números inteiros e retorne o menor valor e o maior valor da array, no seguinte formato: "o menor número é X e o maior número é Y". 28 | // Exemplo, recebendo [5, 37, 18, 59, 12, -5] a função deve retornar "o maior número é 59 e o menor número é -5" 29 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/exemplos.js: -------------------------------------------------------------------------------- 1 | function soma(numero1, numero2) { 2 | const somaTotal = numero1 + numero2 3 | const nome = olar("Jessica") 4 | return `o resultado é ${somaTotal}, ${nome}` 5 | } 6 | 7 | function olar(nome) { 8 | return `oi ${nome}!` 9 | } 10 | 11 | /////////////////////////////////// 12 | 13 | let numeroWhile = 13 14 | while (numeroWhile <= 12) { 15 | console.log("numero while", numeroWhile) 16 | numeroWhile++ 17 | } 18 | 19 | let numeroDo = 0 20 | do { 21 | console.log("numero do", numeroDo) 22 | numeroDo++ 23 | } while (numeroDo < 2) 24 | 25 | /////////////////////////////////// 26 | 27 | // inicial 12 true/false o que acontece depois 28 | 29 | for (let numero = 50; numero >= 0; numero = numero - 5) { 30 | console.log(numero) 31 | } 32 | 33 | //1 - O QUE QUEREMOS QUE REPITA { } 34 | //2 - O QUE QUEREMOS QUE MUDE A CADA LOOP 35 | //3 - QUANDO QUEREMOS QUE PARE 36 | 37 | const nome = "Juliana" 38 | console.log("console do nome", nome.length) 39 | 40 | ///////////////////////// 41 | 42 | // 7) Crie uma função com as seguintes características: 43 | // 1. A função deve receber 3 parâmetros. 44 | // 2. Se somente um parâmetro for passado, retorne o valor do parâmetro. 45 | // 3. Se dois parâmetros forem passados, retorne a soma dos dois parâmetros. 46 | // 4. Se todos os parâmetros forem passados, retorne a soma do primeiro com o segundo, e o resultado dividido pelo terceiro. 47 | // 5. Se nenhum parâmetro for passado, retorne "não recebeu parâmetro" 48 | 49 | function recebeTresParametros(param1, param2, param3) { 50 | if (param1 != undefined && param2 === undefined && param3 === undefined) { 51 | return param1 52 | } else if (param1 != undefined && param2 != undefined && param3 === undefined) { 53 | return param1 + param2 54 | } else if (param1 != undefined && param2 != undefined && param3 != undefined) { 55 | return (param1 + param2) / param3 56 | } else { 57 | return "não recebeu parâmetro" 58 | } 59 | } 60 | 61 | console.log(recebeTresParametros(2, 2, 2)) // 2 62 | 63 | 64 | ///////////////////////// 65 | 66 | // imprimir na tela os números de 0 a 10 67 | 68 | // inicial enquanto depois de cada loop 69 | for (let numero = 0; numero <= 10; numero++) { 70 | console.log("sei lá quantas vezes vai rodar") 71 | } 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-extra.js: -------------------------------------------------------------------------------- 1 | // DESAFIO - validador de cartão de crédito 2 | 3 | // Todos os números de cartão de crédito têm uma sequência que pode ser validada através de um algoritmo chamado Algoritmo de Luhn. Para validar qualquer número de cartão de crédito (o padrão de 16 dígitos), siga os seguintes passos: 4 | 5 | // 1. Retire o último dígito do número. Ele é o verificador; 6 | // 2. Escreva os números na ordem inversa; 7 | // 3. Multiplique os dígitos das casas ímpares por 2 e subtraia 9 de todos os resultados maiores que 9; 8 | // 4. Some todos os números; 9 | // 5. O dígito verificador (aquele do passo 1) é o número que você precisa somar a todos os outros números somados para fazer a validação; 10 | // 6. O número de cartão de crédito será válido caso o total (do passo 5) seja múltiplo de 10 (ou seja, numero % 10 === 0) 11 | 12 | // Números de cartões válidos para teste: 13 | 14 | // 5555666677778884 15 | // 5485755481460022 16 | // 5141331902596939 17 | // 5381579886310193 18 | // 5261400319746371 19 | 20 | 21 | /////////////////////// 22 | 23 | // DESAFIO - saudar clientes 24 | 25 | // Escreva uma função chamada saudarCliente. 26 | // Essa função deve receber um nome, verificar se ele existe na base de clientes e retornar uma saudação com base em quantas vezes a cliente visitou um estabelecimento. 27 | // Consulte o objeto baseClientes abaixo. A saudação deve ser diferente, dependendo do nome da reserva. 28 | 29 | // Caso 1 - Cliente desconhecida (o nome não está presente no objeto baseClientes) 30 | // console.log(saudarCliente('Chiquinha')) // --> 'Olá, é a primeira vez por aqui?' 31 | 32 | // Caso 2 - Cliente que visitou apenas uma vez (o valor de 'visitas' é 1) 33 | // console.log(saudarCliente('Clotilde')) // --> 'Bem-vinda, Clotilde! Que bom que voltou!' 34 | 35 | // Caso 3 - Cliente repetida: (o valor de 'visitas' é maior que 1) 36 | // console.log(saudarCliente('Florinda')) // --> 'Bem-vinda mais uma vez, Florinda!' 37 | 38 | // Notas: 39 | // Sua função não deve alterar o objeto baseClientes para atualizar o número de visitas. 40 | // Não codifique os dados exatos da amostra. Esta é uma má ideia: 41 | // if (nomeCliente === 'Maria') { 42 | // // etc 43 | // } 44 | 45 | const baseClientes = { 46 | Clotilde: { 47 | visitas: 1, 48 | }, 49 | Florinda: { 50 | visitas: 2, 51 | }, 52 | Paty: { 53 | visitas: 3, 54 | }, 55 | } 56 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-extra-resolvidos.js: -------------------------------------------------------------------------------- 1 | // 1) Calcule a potência de 2 elevado a um número específico. Deve usar um loop (não usar `Math.pow()`). 2 | // Exemplo: 3 | // potenciaDeDois(10) // 1024 4 | 5 | function potenciaDeDois(numero) { 6 | let resultado = 1 7 | while (numero > 0) { 8 | resultado *= 2 9 | numero -= 1 10 | } 11 | return resultado 12 | } 13 | 14 | 15 | // 2) Crie uma função que receba três números e determine se um número é maior que outro. 16 | // Exemplo: 17 | // retornaNumMaior(10, 20, 30) // 30 18 | 19 | function retornaNumMaior(num1, num2, num3) { 20 | 21 | let maior = num1; 22 | 23 | if (num1 > num2) { 24 | if (num1 > num3) { 25 | maior = num1 26 | } else { 27 | maior = num3 28 | } 29 | } else if (num2 > num3) { 30 | maior = num2 31 | } else { 32 | maior = num3 33 | } 34 | return maior 35 | } 36 | 37 | // *************** 38 | 39 | // DESAFIOS! 40 | 41 | // Crie uma função que determina se um número é primo e retorne true ou false conforme o caso. Em matemática, um número primo é um número natural maior que 1 que é divisível somente por ele mesmo e 1. Utilize o operador módulo (`%`) para determinar se um número é divisível por outro. 42 | 43 | function numPrimo(num) { 44 | if (num === 1) { 45 | return true 46 | } 47 | for (let i = 2; i < num; i++) { 48 | if (num % i === 0) { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | // Crie uma função que conte o número de vogais em uma `string` e retorne o número de vogais. 56 | // Exemplo: 57 | // function contaVogais("carro") // 2 58 | 59 | function contaVogais(string) { 60 | const vogais = 'aeiou' 61 | const arrayMinusculas = string.toLowerCase() 62 | let totalVogais = 0 63 | 64 | for (let i = 0; i < arrayMinusculas.length; i += 1) { 65 | for (let j = 0; j < vogais.length; j += 1) { 66 | if (arrayMinusculas[i] === vogais[j]) { 67 | totalVogais += 1 68 | } 69 | } 70 | } 71 | return totalVogais 72 | } 73 | 74 | // Use estruturas de controle para inverter uma array de inteiros. A função deverá receber uma array de números e retornar uma array com a ordem dos elementos invertida. Não é válido utilizar `arr.reverse()`. 75 | // Exemplo: 76 | // function inverteArray([1, 2, 3, 4]) // [4, 3, 2, 1] 77 | 78 | function inverteArray(array) { 79 | const arrayInvertida = [] 80 | for (let i = array.length - 1; i >= 0; i -= 1) { 81 | arrayInvertida.push(array[i]) 82 | } 83 | return arrayInvertida 84 | } 85 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-funcoes.js: -------------------------------------------------------------------------------- 1 | // **Você pode dar os nomes que quiser para as funções e variáveis, apenas lembre que eles devem ser semânticos :) 2 | 3 | // 1) crie uma função para cada uma das operações básicas (soma, subtração, multiplicação e divisão), cada uma delas recebendo 2 números como parâmetros e retornando o resultado 4 | 5 | 6 | // 2) para esse exercício, as funções de multiplicação e divisão não devem aceitar valores iguais a 0 (zero). Adicione esta lógica nas funções. 7 | 8 | 9 | // 3) crie uma função que chame internamente qualquer uma das funções acima e imprima o resultado no formato de String. Exemplo: "O resultado da operação é X" (sendo X o valor do resultado). 10 | 11 | 12 | // 4) utilizando as funções de soma e multiplicação já feitas nos exercícios anteriores, crie uma nova função que chame essas funções e resolva a conta 36325 * (9824 + 777). 13 | 14 | 15 | // 5) crie uma função que receba dois números e gere outros dois números aleatórios com valores entre eles. Exemplo: uma função que receba (1, 100) deve gerar dois números aleatórios entre 1 e 100 (por exemplo, 54 e 12). Em seguida, some estes números e devolva uma string com o resultado no formato: "a soma de [número aleatório] e [número aleatório] é XXX". Você vai ter que pesquisar o método do JS para gerar números aleatórios, `Math.random()` e como utilizá-lo. 16 | 17 | 18 | // 6) Crie uma função com as seguintes características: 19 | // 1. A função deve receber 3 números 20 | // 2. Se qualquer um dos três números não forem informados, a função deve retornar a string: "Preencha todos os valores corretamente!" 21 | // 3. O retorno da função deve ser a multiplicação dos 3 números, somando `2` ao resultado da multiplicação. DICA: pesquise o que aparece no console.log caso uma função precise de um parâmetro, mas não receba nenhum. 22 | 23 | 24 | // 7) Crie uma função com as seguintes características: 25 | // 1. A função deve receber 3 parâmetros. 26 | // 2. Se somente um parâmetro for passado, retorne o valor do parâmetro. 27 | // 3. Se dois parâmetros forem passados, retorne a soma dos dois parâmetros. 28 | // 4. Se todos os parâmetros forem passados, retorne a soma do primeiro com o segundo, e o resultado dividido pelo terceiro. 29 | // 5. Se nenhum parâmetro for passado, retorne "não recebeu parâmetro" 30 | 31 | 32 | // 8) crie uma função que receba uma string como parâmetro, e retorne essa mesma string invertida. Por exemplo, recebendo "reprograma", vai retornar "amargorper". Para isso, você vai ter que pesquisar como usar JavaScript para inverter uma string. 33 | 34 | 35 | // 9) agora que você já sabe reverter strings, crie uma função que receba uma string, verifique se é um palíndromo e retorne true ou false. Exemplo de palíndromo: "arara". 36 | 37 | 38 | // 10) crie uma função que receba duas strings como parâmetros e retorne a string com a maior quantidade de caracteres. Por exemplo, se passarmos como parâmetro "banana" e "chocolate" a função deve retornar "chocolate" 39 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-for.js: -------------------------------------------------------------------------------- 1 | const input = require('readline-sync') 2 | 3 | // 1) crie uma função que receba uma string e devolva seu valor em letras maiúsculas, separadas por um espaço. Exemplo: 'banana' -> 'B A N A N A' 4 | 5 | 6 | // 2) crie uma função que receba um número e devolva uma soma progressiva. Por exemplo, recebendo o número 5, a função deve retornar 15, ou seja, o resultado de 1 + 2 + 3 + 4 + 5. 7 | 8 | 9 | // 3) crie um programa que pergunta seu nome. Depois que digitar o nome, o programa deverá responder 'Olá [nome]'. 10 | // Enquanto digitar qualquer palavra, print o que foi digitado mas avise que, para sair, é só dizer 'Tchau'. 11 | // O programa vai dizer 'Tchau [nome]' e finalizar. 12 | 13 | 14 | // 4) crie uma função que receba dois números e exiba no console uma contagem regressiva entre eles, contando de dois em dois números. Por exemplo: recebendo o número inicial 20 e o final 0, a função deverá imprimir em sequência 20 18 16 14 12 10 8 6 4 2 0. 15 | 16 | 17 | // 5) crie uma função que receba um número e imprima no console de 0 até o número informado. Além disso, cada vez que imprimir o número, informe se é par ou ímpar. Exemplo: recebendo 5, deve imprimir: "0 é par", "1 é ímpar", "2 é par", "3 é ímpar", "4 é par", "5 é ímpar". 18 | 19 | 20 | // 6) crie uma função que receba um número inteiro e imprima os números no console em ordem, de 1 até o número. Porém, para todos os números que forem múltiplos de 3, imprima na tela "banana" ao invés do número; para os números múltiplos de 5, imprima "biscoito". Para números múltiplos de 3 e 5, imprima "biscoito de banana". Exemplo, recebendo 15 o resultado será: 21 | // 1 22 | // 2 23 | // banana 24 | // 4 25 | // biscoito 26 | // banana 27 | // 7 28 | // 8 29 | // banana 30 | // biscoito 31 | // 11 32 | // banana 33 | // 13 34 | // 14 35 | // biscoito de banana 36 | 37 | 38 | // 7) crie uma função que receba um número positivo inteiro, itere de 1 ao número e some SOMENTE todos os números múltiplos de 3 OU 5. Por exemplo, recebendo 15, o valor retornado deverá ser 60, ou seja, a soma de todos os números múltiplos de 3 ou 5 entre 0 e 15 (3 + 5 + 6, etc). 39 | 40 | 41 | // 8) altere a função acima para, ao invés de somar múltiplos de 5 ou 3, fazer isso com qualquer número de 1 a 9. Os números serão recebidos via parâmetro de função, por exemplo: `function somaMultiplos(num, multiplo1, multiplo2)` pode ser chamada com os valores `somaMultiplos(100, 2, 4) e verificar os números múltiplos de 2 e 4. Extra: antes de seguir com o cálculo, verificar se os números recebidos estão mesmo entre 1 e 9; caso não estejam, imprimir o aviso "informe múltiplos de 1 a 9" e encerrar o programa. 42 | 43 | 44 | // 9) crie uma função que receba um número qualquer devolva o seguinte padrão como resultado (inclusive com os espaços). Por exemplo, caso receba o número 5 como parâmetro: 45 | // * 46 | // ** 47 | // *** 48 | // **** 49 | // ***** 50 | 51 | 52 | // DESAFIO EXTRA: refaça o exercício acima, porém agora com o seguinte padrão: 53 | // * 54 | // ** 55 | // *** 56 | // **** 57 | // ***** 58 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-extra-resolvidos.js: -------------------------------------------------------------------------------- 1 | // DESAFIO - validador de cartão de crédito 2 | 3 | // Todos os números de cartão de crédito têm uma sequência que pode ser validada através de um algoritmo chamado Algoritmo de Luhn. Para validar qualquer número de cartão de crédito (o padrão de 16 dígitos), siga os seguintes passos: 4 | 5 | // 1. Retire o último dígito do número. Ele é o verificador; 6 | // 2. Escreva os números na ordem inversa; 7 | // 3. Multiplique os dígitos das casas ímpares por 2 e subtraia 9 de todos os resultados maiores que 9; 8 | // 4. Some todos os números; 9 | // 5. O dígito verificador (aquele do passo 1) é o número que você precisa somar a todos os outros números somados para fazer a validação; 10 | // 6. O número de cartão de crédito será válido caso o total (do passo 5) seja múltiplo de 10 (ou seja, numero % 10 === 0) 11 | 12 | // Números de cartões válidos para teste: 13 | 14 | // 5555666677778884 15 | // 5485755481460022 16 | // 5141331902596939 17 | // 5381579886310193 18 | // 5261400319746371 19 | 20 | // SOLUÇÃO - VERSÃO "LONGA" 21 | 22 | const arrayNumeros = "5555666677778884".split('') 23 | const ultimoDigito = Number(arrayNumeros.pop()) 24 | const arrayMultiplicaESoma = arrayNumeros 25 | .reverse() 26 | .map((numero, i) => { 27 | if (i % 2 === 0) { 28 | if (numero >= 5) { 29 | return (numero * 2) - 9 30 | } 31 | return numero * 2 32 | } 33 | return Number(numero) 34 | }) 35 | const valorFinal = arrayMultiplicaESoma 36 | .reduce((atual, acumulador) => atual + acumulador, ultimoDigito) 37 | const numeroEhValido = valorFinal % 10 === 0 ? true : false 38 | 39 | console.log(numeroEhValido) 40 | 41 | /////////////////////// 42 | 43 | // DESAFIO - saudar clientes 44 | 45 | // Escreva uma função chamada saudarCliente. 46 | // Essa função deve receber um nome, verificar se ele existe na base de clientes e retornar uma saudação com base em quantas vezes a cliente visitou um estabelecimento. 47 | // Consulte o objeto baseClientes abaixo. A saudação deve ser diferente, dependendo do nome da reserva. 48 | 49 | // Caso 1 - Cliente desconhecida (o nome não está presente no objeto baseClientes) 50 | // console.log(saudarCliente('Chiquinha')) // --> 'Olá, é a primeira vez por aqui?' 51 | 52 | // Caso 2 - Cliente que visitou apenas uma vez (o valor de 'visitas' é 1) 53 | // console.log(saudarCliente('Clotilde')) // --> 'Bem-vinda, Clotilde! Que bom que voltou!' 54 | 55 | // Caso 3 - Cliente repetida: (o valor de 'visitas' é maior que 1) 56 | // console.log(saudarCliente('Florinda')) // --> 'Bem-vinda mais uma vez, Florinda!' 57 | 58 | // Notas: 59 | // Sua função não deve alterar o objeto baseClientes para atualizar o número de visitas. 60 | // Não codifique os dados exatos da amostra. Esta é uma má ideia: 61 | // if (nomeCliente === 'Maria') { 62 | // // etc 63 | // } 64 | 65 | const baseClientes = { 66 | Clotilde: { 67 | visitas: 1, 68 | }, 69 | Florinda: { 70 | visitas: 2, 71 | }, 72 | Paty: { 73 | visitas: 3, 74 | }, 75 | } 76 | 77 | const saudarCliente = (nomeCliente) => { 78 | if (!baseClientes[nomeCliente]) { 79 | return 'Olá, é a primeira vez por aqui?' 80 | } 81 | 82 | if (baseClientes[nomeCliente].visitas === 1) { 83 | return `Bem-vinda, ${nomeCliente}! Que bom que voltou!` 84 | } 85 | 86 | if (baseClientes[nomeCliente].visitas > 1) { 87 | return `Bem-vinda mais uma vez, ${nomeCliente}!` 88 | } 89 | 90 | return undefined 91 | } 92 | 93 | console.log(saudarCliente('Chiquinha')) -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-array-resolvidos.js: -------------------------------------------------------------------------------- 1 | // Exercícios práticos com for e arrays! 2 | 3 | // 1) Crie uma função que receba uma array e imprima no console o número do índice e o elemento. 4 | // Exemplo: recebendo ["banana", "gatinho", "brócolis"] deve imprimir no console: 5 | // índice 0, elemento "banana" 6 | // índice 1, elemento "gatinho" 7 | // índice 2, elemento "brócolis" 8 | 9 | const arrei = ["banana", "gatinho", "brócolis"] 10 | 11 | function imprimeIndiceEElemento(arr) { 12 | for (let i = 0; i < arr.length; i++) { 13 | console.log(`índice ${i}, elemento ${arr[i]}`) 14 | } 15 | } 16 | 17 | imprimeIndiceEElemento(arrei) 18 | 19 | // 2) Crie uma função que receba uma array de números inteiros e retorne a soma dos elementos. 20 | // Exemplo: recebendo [10,11,12] deve retornar 33 21 | 22 | const arrNums = [10,11,12,10,11,12,10,11,12,10,11,12] 23 | 24 | function soma(arr) { 25 | let total = 0 26 | for (let i = 0; i < arr.length; i++) { 27 | total += arr[i] 28 | } 29 | return total 30 | } 31 | 32 | console.log(soma(arrNums)) 33 | 34 | // 3) Crie uma função que receba uma array de números inteiros e retorne outra array somente com os elementos maiores que 5. 35 | // Exemplo, recebendo [88,55,0,2,85,81,24,12] deve retornar [ 88, 55, 85, 81, 24, 12 ] 36 | 37 | function maioresQueCinco(arr) { 38 | const numerosMaiores = [] 39 | for (let i = 0; i < arr.length; i++) { 40 | if (arr[i] > 5) { 41 | numerosMaiores.push(arr[i]) 42 | } 43 | } 44 | return numerosMaiores 45 | } 46 | 47 | console.log(maioresQueCinco([88,55,0,2,85,81,24,12])) 48 | 49 | // 4) Modifique a função anterior para que receba, além da array, o número para comparação (não deixar mais fixo como número 5). 50 | // Exemplo, recebendo ([88,55,0,2,85,81,24,12], 20) deve retornar [ 88, 55, 85, 81, 24 ] 51 | 52 | function maioresQueNumero(arr, num) { 53 | const numerosMaiores = [] 54 | for (let i = 0; i < arr.length; i++) { 55 | if (arr[i] > num) { 56 | numerosMaiores.push(arr[i]) 57 | } 58 | } 59 | return numerosMaiores 60 | } 61 | 62 | console.log(maioresQueNumero([88,55,0,2,85,81,24,12], 20)) 63 | 64 | // 5) Crie uma função que receba uma array de números inteiros e retorne o maior número encontrado. 65 | // Exemplo: recebendo [56, 12, 168, 66] deve retornar 168 66 | // EXTRA: Pesquisar uma maneira iniciar com o menor número possível (dica: não é zero) 67 | 68 | function maiorNumero(arr){ 69 | // let maiorNum = Number.NEGATIVE_INFINITY 70 | let maiorNum = arr[0] 71 | for (let i = 0; i < arr.length ; i++) { 72 | if (maiorNum < arr[i]) { 73 | maiorNum = arr[i] 74 | } 75 | } 76 | return maiorNum 77 | } 78 | 79 | // console.log(maiorNumero([56, 12, 168, 66])) 80 | 81 | // 6) Crie uma função que receba uma array de números inteiros e retorne o menor valor e o maior valor da array, no seguinte formato: "o menor número é X e o maior número é Y". 82 | // Exemplo, recebendo [5, 37, 18, 59, 12, -5] a função deve retornar "o maior número é 59 e o menor número é -5" 83 | 84 | const arrMenoresMaiores = [5, 37, 18, 59, 12, -5] 85 | 86 | function imprimeMaiorEMenor(arr) { 87 | 88 | let maior = 0 89 | let menor = 0 90 | 91 | for(let i = 0; i < arr.length; i++) { 92 | if (arr[i] > maior) { 93 | maior = arr[i] 94 | } 95 | if (arr[i] < menor) { 96 | menor = arr[i] 97 | } 98 | } 99 | return `o maior número é ${maior} e o menor número é ${menor}` 100 | } 101 | 102 | console.log(imprimeMaiorEMenor(arrMenoresMaiores)) 103 | 104 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exercicios-obj-resolvidos.js: -------------------------------------------------------------------------------- 1 | // 1) Crie uma função que receba 3 parâmetros: o nome de um livro, a quantidade de páginas e a autoria. Retorne um objeto no formato: {titulo: "nome do livro", paginas: "número de páginas", autoria: "nome da pessoa"} 2 | 3 | // Exemplo: 4 | // objLivro('Antes do Baile Verde', 234, 'Lygia Fagundes Telles') 5 | 6 | // retorna o objeto: 7 | // { 8 | // titulo: 'Antes do Baile Verde', 9 | // paginas: 234, 10 | // autoria: 'Lygia Fagundes Telles' 11 | // } 12 | 13 | function objLivro(titulo, paginas, autoria) { 14 | return ({ 15 | titulo, // mesma coisa que titulo: titulo 16 | paginas, 17 | autoria 18 | }) // parenteses para retornar o objeto diretamente 19 | } 20 | 21 | console.log(objLivro('Antes do Baile Verde', 234, 'Lygia Fagundes Telles')) 22 | 23 | // 2) Aproveite a função acima em outra função, que deve retornar a seguinte frase: "O livro XXXX foi escrito por XXX e tem XXX páginas". Você deve utilizar a função que já está pronta, e não reescrever a lógica dela dentro dessa nova função. 24 | 25 | function fraseLivro(obj) { 26 | return `O livro ${obj.titulo} foi escrito por ${obj.autoria} e tem ${obj.paginas} páginas` 27 | } 28 | 29 | // console.log(fraseLivro(objLivro('Antes do Baile Verde', 234, 'Lygia Fagundes Telles'))) 30 | 31 | // 3) Crie uma função que receba um objeto como o abaixo: 32 | 33 | // const pessoa = { 34 | // nome: 'Nazaré', 35 | // sobrenome: 'Tedesco', 36 | // } 37 | 38 | // Dado um objeto que tem uma propriedade 'nome' e uma propriedade 'sobrenome', a função deve retornar um novo objeto com as mesmas propriedades que o objeto recebido e mais uma propriedade, chamada 'nomeCompleto', cujo valor é uma string com o nome e sobrenome separados por um espaço. 39 | 40 | // Exemplo de retorno: 41 | // { 42 | // nome: 'Nazaré', 43 | // sobrenome: 'Tedesco', 44 | // nomeCompleto: 'Nazaré Tedesco' 45 | // } 46 | 47 | function nomeCompleto(obj) { 48 | const novoObj = { 49 | nome: obj.nome, 50 | sobrenome: obj.sobrenome, 51 | nomeCompleto: `${obj.nome} ${obj.sobrenome}` 52 | } 53 | return novoObj 54 | } 55 | 56 | // VERSÃO COM ARROW FUNCTION E DESCONSTRUÇÃO 57 | // const addFullNameProperty = obj => ({ 58 | // ...obj, 59 | // fullName: `${obj.firstName} ${obj.lastName}`, 60 | // }); 61 | 62 | const pessoa = { 63 | nome: 'Nazaré', 64 | sobrenome: 'Tedesco', 65 | } 66 | 67 | // console.log(nomeCompleto(pessoa)) 68 | 69 | // 4) Crie uma função que receba o objeto abaixo e o nome de uma das chaves, e retorne a soma de todos os elementos do array que for selecionado através da chave. 70 | 71 | const objArrays = { 72 | array1: [1, 2, 3], 73 | array2: [5, 6, 7, 8], 74 | array3: [9, 9, 9], 75 | } 76 | 77 | function somaArray(obj, chave) { 78 | let total = 0 79 | const arr = obj[chave] 80 | for (let i = 0; i < arr.length; i++) { 81 | total += arr[i] 82 | } 83 | return total 84 | } 85 | // forEach não retorna nada, só faz 86 | function somaArrayForEach(obj, chave) { 87 | let total = 0 88 | obj[chave].forEach( function(indice) { 89 | total += indice 90 | }) 91 | return total 92 | } 93 | // map SEMPRE retorna uma array 94 | function somaArrayMap(obj, chave) { 95 | let total = 0 96 | const arrResultados = obj[chave].map( function(indice) { 97 | total += indice 98 | return total 99 | }) 100 | return arrResultados 101 | } 102 | 103 | console.log(somaArray(objArrays, 'array2')) // 26 104 | console.log(somaArrayForEach(objArrays, 'array2')) // 26 105 | console.log(somaArrayMap(objArrays, 'array2')) // [ 5, 11, 18, 26 ] 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/exemplos.js: -------------------------------------------------------------------------------- 1 | // DICAS DE DEBUGAGEM PRA VIDA 2 | // sempre verificar o que a função espera receber 3 | // verificar colchetes, parênteses e chaves 4 | // ler os erros - encontrar a linha 5 | // sempre verificar o que os MÉTODOS/funções retornam 6 | // sempre pensar nas """substituições""" das variáveis pelos valores que estão dentro delas 7 | // sempre verificar o que estamos recebendo em uma variável pra ver se é o que esperamos 8 | 9 | // 0 1 2 3 4 5 // índice/posição 10 | const numeros = [65, 842, 89, 789, 6, 9] //cada elemento 11 | 12 | for (let i = 0; i < numeros.length; i++) { 13 | // i: número do índice nomeDaArray[i]: elemento 14 | console.log(`índice: ${i}, elemento: ${numeros[i]}`) 15 | } 16 | 17 | //métodos de array 18 | const indiceDaArray = numeros.indexOf(789) 19 | console.log(indiceDaArray) 20 | 21 | //push para "empurrar" elementos pra dentro de uma array 22 | const arrayNumeros = [] 23 | for (let i = 0; i <= 10; i++) { 24 | arrayNumeros.push(`índice ${i}`) 25 | } 26 | console.log(arrayNumeros) 27 | 28 | // OBJETOS 29 | 30 | const alunasOn7 = [ 31 | { nome: "Juliana", idade: 39, pets: ["Satanás", "Churrumina"] }, 32 | { nome: "Helena", idade: 28, pets: ["gato 1", "gato 2"] }, 33 | { nome: "Carla", idade: 35, pets: ["Risoto"] } 34 | ] 35 | 36 | const objAluna = { 37 | nome: "Juliana", 38 | idade: 39, 39 | pets: ["Satanás", "Churrumina"], 40 | irmaos: [{ nomeCompleto: "Beta" }, { nomeCompleto: "Rê" }], // array de objetos 41 | cidade: { 42 | nome: { 43 | nomeCompleto: "São Paulo", 44 | apelidinho: "Sampa" 45 | }, 46 | bairro: "Pinheiros" 47 | }, 48 | } 49 | 50 | // como acessar uma array de objetos e fazer modificações em cada um 51 | for (let i = 0; i < objAluna.irmaos.length; i++) { 52 | objAluna.irmaos[i].ehNerd = true 53 | } 54 | 55 | // map, forEach: funções que precisam de funções dentro delas (callbacks) 56 | 57 | // map SEMPRE retorna uma array de elementos 58 | const novaArray = objAluna.irmaos.map(function(elementoDaArray) { 59 | return elementoDaArray.nomeCompleto 60 | }) 61 | // console.log(novaArray) 62 | 63 | // forEach não retorna nada, só faz 64 | // objAluna.irmaos.forEach(function(elementoDaArray) { 65 | // console.log(elementoDaArray.nomeCompleto) 66 | // }) 67 | 68 | //notação de ponto 69 | console.log(objAluna.idade) 70 | //notação de colchete 71 | const variavel = 'idade' 72 | console.log(objAluna[variavel]) 73 | 74 | // criando ou alterando chaves e valores de um objeto 75 | 76 | // objetos têm propriedades/características 77 | // objetos têm comportamentos 78 | const objGato = { 79 | nome: "Satanás", 80 | miar: function(nome){ 81 | return `miau, ${nome}` 82 | } 83 | } 84 | 85 | console.log(objGato.miar('Satanás')) 86 | 87 | const pokemons = 88 | [{ 89 | id: 1, 90 | name: "Bulbasaur", 91 | type: [ "Grass", "Poison" ], 92 | }, 93 | { 94 | id: 2, 95 | name: "Ivysaur", 96 | type: [ "Grass", "Poison" ], 97 | }, 98 | { 99 | id: 4, 100 | name: "Charmander", 101 | type: [ "Fire" ], 102 | }] 103 | 104 | const nomesPokemons = pokemons.map(function(pokemon) { 105 | return pokemon.name 106 | }) 107 | 108 | console.log(nomesPokemons) 109 | 110 | pokemons.forEach(function(pokemon) { 111 | pokemon.name = "banana" 112 | }) 113 | 114 | console.log(pokemons) 115 | 116 | // //a mesma coisa, com arrow function 117 | // let outraListaNomes = '' 118 | // const nomesPokemonsArrow = pokemons.forEach(pokemon => outraListaNomes += `O pokemón ${pokemon.name} tem id ${pokemon.id}\n`) 119 | // console.log(outraListaNomes) 120 | 121 | for (let i = 0; i < pokemons.length; i++) { 122 | console.log(`nome: ${pokemons[i].name}`) 123 | } 124 | 125 | const arr = [54, 65, 45, 56, 76] 126 | 127 | const multiplicaIndicesPares = arr.map((numero, indice) => { 128 | if (indice % 2 === 0) { 129 | return numero * 2 130 | } 131 | return numero 132 | }) 133 | 134 | console.log(multiplicaIndicesPares) -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-for-resolvidos.js: -------------------------------------------------------------------------------- 1 | const input = require('readline-sync') 2 | 3 | // 1) crie uma função que receba uma string e devolva seu valor em letras maiúsculas, separadas por um espaço. Exemplo: 'banana' -> 'B A N A N A' 4 | 5 | function modificaString(string){ 6 | let stringModificada = '' 7 | for (let i = 0; i < string.length; i++) { 8 | stringModificada += string[i].toUpperCase() + ' ' 9 | } 10 | return stringModificada 11 | } 12 | 13 | // 2) crie uma função que receba um número e devolva uma soma progressiva. Por exemplo, recebendo o número 5, a função deve retornar 15, ou seja, o resultado de 1 + 2 + 3 + 4 + 5. 14 | 15 | function soma(num) { 16 | let total = 0 17 | for (let i = 0; i <= num; i++) { 18 | // total = total + i 19 | total += i 20 | } 21 | return total 22 | } 23 | 24 | // 3) crie um programa que pergunta seu nome. Depois que digitar o nome, o programa deverá responder 'Olá [nome]'. 25 | // Enquanto digitar qualquer palavra, print o que foi digitado mas avise que, para sair, é só dizer 'Tchau'. 26 | // O programa vai dizer 'Tchau [nome]' e finalizar. 27 | 28 | function imprimeComandos() { 29 | 30 | let nome = input.question('digite seu nome: ') 31 | console.log(`Olá, ${nome}`) 32 | 33 | let texto = '' 34 | 35 | do { 36 | texto = input.question('digite algo ou "Tchau" para sair: ') 37 | console.log(`Você digitou: ${texto}`) 38 | } while (texto != 'Tchau') 39 | 40 | console.log(`Tchau, ${nome}!`) 41 | } 42 | 43 | // 4) crie uma função que receba dois números e exiba no console uma contagem regressiva entre eles, contando de dois em dois números. Por exemplo: recebendo o número inicial 20 e o final 0, a função deverá imprimir em sequência 20 18 16 14 12 10 8 6 4 2 0. 44 | 45 | // 20 0 46 | function contagemRegressiva(numInicial, numFinal) { 47 | for (let i = numInicial; i >= numFinal; i -= 2) { 48 | console.log(i) 49 | } 50 | } 51 | 52 | // 5) crie uma função que receba um número e imprima no console de 0 até o número informado. Além disso, cada vez que imprimir o número, informe se é par ou ímpar. Exemplo: recebendo 5, deve imprimir: "0 é par", "1 é ímpar", "2 é par", "3 é ímpar", "4 é par", "5 é ímpar". 53 | 54 | function imprimeParImpar(num) { 55 | for (let i = 0; i <= num; i++) { 56 | if (i === 0) { 57 | console.log(`${i} é par`) 58 | } 59 | else if (i % 2 === 0) { 60 | console.log(`${i} é par`) 61 | } 62 | else { 63 | console.log(`${i} é ímpar`) 64 | } 65 | } 66 | } 67 | 68 | // 6) crie uma função que receba um número inteiro e imprima os números no console em ordem, de 1 até o número. Porém, para todos os números que forem múltiplos de 3, imprima na tela "banana" ao invés do número; para os números múltiplos de 5, imprima "biscoito". Para números múltiplos de 3 e 5, imprima "biscoito de banana". Exemplo, recebendo 15 o resultado será: 69 | // 1 70 | // 2 71 | // banana 72 | // 4 73 | // biscoito 74 | // banana 75 | // 7 76 | // 8 77 | // banana 78 | // biscoito 79 | // 11 80 | // banana 81 | // 13 82 | // 14 83 | // biscoito de banana 84 | 85 | function biscoitoBanana(num) { 86 | for (let i = 1; i <= num; i++) { 87 | if (i % 3 === 0 && i % 5 === 0) { 88 | console.log('biscoito de banana') 89 | } else if (i % 3 === 0 && i % 5 != 0) { 90 | console.log('banana') 91 | } else if (i % 5 === 0 && i % 3 != 0) { 92 | console.log('biscoito') 93 | } else { 94 | console.log(i) 95 | } 96 | } 97 | } 98 | 99 | // 7) crie uma função que receba um número positivo inteiro, itere de 1 ao número e some SOMENTE todos os números múltiplos de 3 OU 5. Por exemplo, recebendo 15, o valor retornado deverá ser 60, ou seja, a soma de todos os números múltiplos de 3 ou 5 entre 0 e 15 (3 + 5 + 6, etc). 100 | 101 | //15 102 | function somaTresOuCinco(num) { 103 | let soma = 0 104 | //15 105 | for (let i = 0; i <= num; i++){ 106 | if (i % 3 === 0 || i % 5 === 0) { 107 | soma += i 108 | } 109 | } 110 | return soma 111 | } 112 | 113 | console.log(somaTresOuCinco(15)) 114 | 115 | // 8) altere a função acima para, ao invés de somar múltiplos de 5 ou 3, fazer isso com qualquer número de 1 a 9. Os números serão recebidos via parâmetro de função, por exemplo: `function somaMultiplos(num, multiplo1, multiplo2)` pode ser chamada com os valores `somaMultiplos(100, 2, 4) e verificar os números múltiplos de 2 e 4. Extra: antes de seguir com o cálculo, verificar se os números recebidos estão mesmo entre 1 e 9; caso não estejam, imprimir o aviso "informe múltiplos de 1 a 9" e encerrar o programa. 116 | 117 | function somaMultiplos(num, multiplo1, multiplo2) { 118 | 119 | if ((multiplo1 < 1 || multiplo1 > 9) || (multiplo2 < 1 || multiplo2 > 9)) { 120 | return 'informe múltiplos de 1 a 9' 121 | } 122 | 123 | let soma = 0 124 | for (let i = 0; i <= num; i++) { 125 | if (i % multiplo1 === 0 || i % multiplo2 === 0) { 126 | soma += i 127 | } 128 | } 129 | return soma 130 | } 131 | 132 | // 9) crie uma função que receba um número qualquer devolva o seguinte padrão como resultado (inclusive com os espaços). Por exemplo, caso receba o número 5 como parâmetro: 133 | // * 134 | // ** 135 | // *** 136 | // **** 137 | // ***** 138 | 139 | function escadinha(num) { 140 | let estrela = '' 141 | for (let i = 0; i <= num; i++) { 142 | estrela += '*' 143 | console.log(estrela) 144 | } 145 | } 146 | 147 | escadinha(10) 148 | 149 | // DESAFIO EXTRA: refaça o exercício acima, porém agora com o seguinte padrão: 150 | // * 151 | // ** 152 | // *** 153 | // **** 154 | // ***** 155 | 156 | function escadinhaContraria(num){ 157 | let espacos = '' 158 | let estrelas = '' 159 | for (let i = 1; i <= num; i++){ 160 | for (let j = 1; j <= num - i; j++){ 161 | espacos += ' ' 162 | } 163 | estrelas += '*' 164 | console.log(espacos + estrelas) 165 | espacos = '' 166 | } 167 | } 168 | 169 | // OUTRA OPÇÃO DE RESPOSTA, USANDO O MÉTODO .repeat() 170 | function escadinhaContraria(num){ 171 | for(let i = 1; i <= num; i++){ 172 | console.log(' '.repeat(num - i) + '*'.repeat(i)) 173 | } 174 | } -------------------------------------------------------------------------------- /funcoes-escopo-loops/exercicios-funcoes-resolvidos.js: -------------------------------------------------------------------------------- 1 | // **Você pode dar os nomes que quiser para as funções e variáveis, apenas lembre que eles devem ser semânticos :) 2 | 3 | // 1) crie uma função para cada uma das operações básicas (soma, subtração, multiplicação e divisão), cada uma delas recebendo 2 números como parâmetros e retornando o resultado 4 | 5 | function soma(numero1, numero2) { 6 | return numero1 + numero2 7 | } 8 | 9 | function subtracao(numero1, numero2) { 10 | return numero1 - numero2 11 | } 12 | 13 | function multiplicacao(numero1, numero2) { 14 | return numero1 * numero2 15 | } 16 | 17 | function divisao(numero1, numero2) { 18 | return numero1 / numero2 19 | } 20 | 21 | function operacoes(num1, num2, operacao) { 22 | switch (operacao) { 23 | case "soma": 24 | return num1 + num2 25 | case "subtracao": 26 | return num1 - num2 27 | case "multiplicacao": 28 | return num1 * num2 29 | case "divisao": 30 | return num1 / num2 31 | } 32 | } 33 | 34 | console.log(soma(2, 2)) 35 | console.log(subtracao(4, 2)) 36 | console.log(multiplicacao(4, 4)) 37 | console.log(divisao(4, 2)) 38 | console.log("CONSOLE LOG DA FUNCAO OPERAÇÕES", operacoes(2, 2, "subtracao")) 39 | 40 | // 2) para esse exercício, as funções de multiplicação e divisão não devem aceitar valores iguais a 0 (zero). Adicione esta lógica nas funções. 41 | 42 | function multiplicaSemZero(num1, num2) { 43 | if (num1 === 0 || num2 === 0) { 44 | return `não queremos zero` 45 | } 46 | return num1 * num2 47 | } 48 | 49 | console.log(multiplicaSemZero(4, 3)) 50 | 51 | function divideSemZero(num1, num2) { 52 | if (num1 === 0 || num2 === 0) { 53 | return `não queremos zero` 54 | } 55 | return num1 / num2 56 | } 57 | 58 | console.log(divideSemZero(10, 2)) 59 | 60 | // 3) crie uma função que chame internamente qualquer uma das funções acima e imprima o resultado no formato de String. Exemplo: "O resultado da operação é X" (sendo X o valor do resultado). 61 | 62 | function imprimeResultado(){ 63 | return `O resultado da operação é ${soma(2, 2)}` 64 | } 65 | 66 | // 4) utilizando as funções de soma e multiplicação já feitas nos exercícios anteriores, crie uma nova função que chame essas funções e resolva a conta 36325 * (9824 + 777). 67 | 68 | function somaEMultiplica() { 69 | // estamos chamando a função multiplicacao e dando 2 parâmetros: o primeiro é o número 36325 e o segundo e o resultado da função soma(9824, 777). O resultado da função soma é 10601, então esse valor será usado como segundo parâmetro da função de multiplicação. 70 | //num1 //resultado da função soma será o num2 71 | return multiplicacao(36325, soma(9824, 777)) 72 | } 73 | 74 | // 5) crie uma função que receba dois números e gere outros dois números aleatórios com valores entre eles. Exemplo: uma função que receba (1, 100) deve gerar dois números aleatórios entre 1 e 100 (por exemplo, 54 e 12). Em seguida, some estes números e devolva uma string com o resultado no formato: "a soma de [número aleatório] e [número aleatório] é XXX". Você vai ter que pesquisar o método do JS para gerar números aleatórios, `Math.random()` e como utilizá-lo. 75 | 76 | function somaAleatorios(min, max) { 77 | const n1 = Math.floor(Math.random() * (max - min + 1)) + min 78 | const n2 = Math.floor(Math.random() * (max - min + 1)) + min 79 | return `a soma de ${n1} e ${n2} é ${n1 + n2}` 80 | } 81 | 82 | // 6) Crie uma função com as seguintes características: 83 | // 1. A função deve receber 3 números 84 | // 2. Se qualquer um dos três números não forem informados, a função deve retornar a string: "Preencha todos os valores corretamente!" 85 | // 3. O retorno da função deve ser a multiplicação dos 3 números, somando `2` ao resultado da multiplicação. DICA: pesquise o que aparece no console.log caso uma função precise de um parâmetro, mas não receba nenhum. 86 | 87 | function multiplicaTresNumeros(num1, num2, num3){ 88 | if (num1 === undefined || num2 === undefined || num3 === undefined){ 89 | return `preencha todos os valores corretamente!` 90 | } 91 | return num1 + num2 + num3 + 2 92 | } 93 | 94 | // 7) Crie uma função com as seguintes características: 95 | // 1. A função deve receber 3 parâmetros. 96 | // 2. Se somente um parâmetro for passado, retorne o valor do parâmetro. 97 | // 3. Se dois parâmetros forem passados, retorne a soma dos dois parâmetros. 98 | // 4. Se todos os parâmetros forem passados, retorne a soma do primeiro com o segundo, e o resultado dividido pelo terceiro. 99 | // 5. Se nenhum parâmetro for passado, retorne "não recebeu parâmetro" 100 | 101 | function recebeTresParametros(param1, param2, param3) { 102 | if (param1 != undefined && param2 === undefined && param3 === undefined) { 103 | return param1 104 | } else if (param1 != undefined && param2 != undefined && param3 === undefined) { 105 | return param1 + param2 106 | } else if (param1 != undefined && param2 != undefined && param3 != undefined) { 107 | return (param1 + param2) / param3 108 | } else { 109 | return "não recebeu parâmetro" 110 | } 111 | } 112 | 113 | console.log(recebeTresParametros(2, 2, 2)) // 2 114 | 115 | // 8) crie uma função que receba uma string como parâmetro, e retorne essa mesma string invertida. Por exemplo, recebendo "reprograma", vai retornar "amargorper". Para isso, você vai ter que pesquisar como usar JavaScript para inverter uma string. 116 | 117 | function inverteString(string){ 118 | return string.split('').reverse().join('') 119 | } 120 | 121 | // 9) agora que você já sabe reverter strings, crie uma função que receba uma string, verifique se é um palíndromo e retorne true ou false. Exemplo de palíndromo: "arara". 122 | 123 | function ehPalindromo(string) { 124 | return ( 125 | string === string.split('').reverse().join('')) 126 | } 127 | 128 | // 10) crie uma função que receba duas strings como parâmetros e retorne a string com a maior quantidade de caracteres. Por exemplo, se passarmos como parâmetro "banana" e "chocolate" a função deve retornar "chocolate" 129 | 130 | function retornaStringMaior(string1, string2){ 131 | if (string1.length > string2.length) { 132 | return string1 133 | } else if (string1.length < string2.length){ 134 | return string2 135 | } else { 136 | return "empatou!" 137 | } 138 | } 139 | 140 | 141 | -------------------------------------------------------------------------------- /funcoes-escopo-loops/readme.md: -------------------------------------------------------------------------------- 1 | # Funções, escopo e loops 2 | 3 | Vmos tratar de mais conceitos *importantes* de lógica de programação com JavaScript. Procure ler com calma e testar livremente os exemplos para internalizar bem! 4 | 5 | [Funções](##-Funções) 6 | * [`return` x `console.log()`](###-Return-x-Console) 7 | * [Declaração de função x expressão de função](###-Declaração-de-Função-x-Expressão-de-função) 8 | * [Arrow Function](###-Arrow-Functions-(função-seta)) 9 | * [IIFE](###-iife) 10 | * [Dicas para escrever funções](###-Dicas) 11 | * [Links e referências](###-Links) 12 | 13 | [Escopos](##-Escopos) 14 | * [Escopos aninhados](###-Nested-Scopes-(escopos-aninhados)) 15 | * [Sombreamento (*shadowing*)](###-Sombreamento) 16 | * [Declaração de `let` em escopos locais](###-Declaração-de-variáveis-no-escopo-local-com-`let`) 17 | 18 | [Loops](##-Loops-ou-laços-de-repetição) 19 | * [while](###-while) 20 | * [do... while](###-do) 21 | * [for](###-for) 22 | * [break](###-break) 23 | * [Diferenças entre `for` e `while`](###-Diferenças-entre-`for`-e-`while`) 24 | 25 | ## Funções 26 | 27 | O que é uma função? 28 | Uma função é um bloco de código/instruções. Usando funções, podemos "chamar" o código que queremos executar, quando queremos executar, e dando para o código as informações que ele precisa. 29 | Por exemplo: 30 | 31 | ```js 32 | //uma função que receba dois números e faça uma soma 33 | 34 | //primeiro momento: declarar a função - ou seja, escrever o que ela faz 35 | function soma(numero1, numero2) { 36 | return numero1 + numero2 37 | } 38 | 39 | //segundo momento: "chamar" a função quando queremos que ela seja executada 40 | soma(1, 1) 41 | //resultado: 2 42 | ``` 43 | 44 | Essa é a estrutura de uma função "clássica". Existem outros jeitos de declarar funções mas vamos entender esse primeiro. 45 | - `function nomeDaFuncao(parametro1, parametro2)`: A palavra-chave `function` avisa o JS que vamos começar a escrever uma função aqui. Em seguida, `nomeDaFuncao` é o nome que vamos dar para ela. Você pode dar o nome que quiser, só não esqueça de seguir a convencaoDeNomesCamelCase 🐪 e de dar pra função **um nome que faça sentido** - ou seja, que diga o que a função faz. 46 | - O trecho entre parênteses são os **parâmetros** `(parametro1, parametro2)`. Você pode dar o nome que quiser também, desde que façam sentido. Os parâmetros são *muito importantes* pois é através deles que a função recebe as informações que precisa para fazer o que queremos. **Importante também**: as funções podem não receber parâmetro nenhum, caso não precise, ou receber quantos precisar. Não tem número mínimo nem máximo. 47 | - A palavra-chave `return` também é muito importante: é ela que "manda pra fora" da função a informação que queremos. Sem o retorno, a função pode fazer várias tarefas, mas nenhum dado que ela processar vai poder ser acessado pelo restante do código. 48 | - Os "momentos": Lembra que usamos funções para que certos trechos de código só sejam executados no momento certo? Então a função também tem dois momentos. No primeiro, quando ela é declarada, escrevemos tudo: nome, o que faz, o que retorna. No segundo momento, quando "chamamos" a função passando os valores que ela precisa, é que ela é executada. *A função não vai ser nunca executada se não chamarmos!* 49 | 50 | Abaixo temos mais exemplos para entendermos melhor cada caso. 51 | 52 | 1. Função sem retorno e sem parâmetro: 53 | ```js 54 | function olar(){ 55 | console.log('oi gente!') 56 | } 57 | 58 | olar() 59 | ``` 60 | 61 | 2. Função sem retorno, com parâmetro: 62 | ```js 63 | function olarPessoa(pessoa){ 64 | console.log(`oi, ${pessoa}!`) 65 | } 66 | 67 | olarPessoa('Helena') 68 | ``` 69 | 70 | 3. Função com retorno, sem parâmetro: 71 | ```js 72 | function escreverOlar(){ 73 | return 'oi gente!' 74 | } 75 | 76 | function escreverOlarPraAlguem(nomePessoa) { 77 | console.log(`${escreverOlar()} Meu nome é ${nomePessoa}`) 78 | } 79 | 80 | escreverOlarParaAlguem('Helena') 81 | ``` 82 | 83 | 4. Função com mais de um parâmetro: 84 | ```js 85 | function operacaoMatematica(numero1, numero2, numero3) { 86 | return numero1 + numero2 + numero3 87 | } 88 | 89 | operacaoMatematica(1, 1, 1) 90 | ``` 91 | 92 | ### Return x Console 93 | 94 | Qual a diferença entre `return` e `console.log()`? 95 | 96 | O `console.log` significa, traduzindo do inglês, "registro no console". Ou seja, é somente um registro pra gente que está desenvolvendo obter alguma informação do código, mas *o `console.log()` não influencia no código, é só pra dar informação!* 97 | 98 | Já o `return` é o comando que usamos quando realmente precisamos que a função "mande pra fora dela" algum dado que precisamos usar em outra parte do código. Ele deve ser sempre a última coisa a ser escrita na última linha antes de fechar a função, pois tudo que vem depois desse comando é ignorado pelo JS. 99 | 100 | Em alguns dos casos acima (casos 1 e 3), a própria função já define `console.log()` então a informação já vai ser exibida no console. Já no caso 4, se quisermos conferir o retorno da função no console, devemos chamá-la no formato: `console.log(operacaoMatematica(1, 1, 1))`. 101 | 102 | ### Declaração de Função x Expressão de função 103 | 104 | A forma que acabamos de ver (que chamei de "clássica") é a que chamamos de declaração de função, com a palavra-chave `function` e depois o nome que damos pra função. 105 | 106 | Outra forma de escrever funções: 107 | 108 | ```js 109 | const olar = function() { 110 | console.log('oi gente!') 111 | } 112 | 113 | olar() 114 | ``` 115 | 116 | Ou, utilizando parâmetros: 117 | 118 | ```js 119 | const soma = function(numero1, numero2) { 120 | return numero1 + numero2 121 | } 122 | 123 | console.log(soma(1, 1)) //resultado: 2 124 | ``` 125 | 126 | Qual a diferença? 127 | 128 | Nessa versão, a função em si não tem nome (é uma função anônima) e chamamos através de uma variável. De resto, escrevemos de forma parecida. 129 | 130 | A diferença está num comportamento do JS chamado içamento, ou *hoisting*. Quando o arquivo JS é carregado, todas as funções declaradas (que têm nome) são içadas, ou puxadas para o topo do contexto. 131 | 132 | O que? Traduzindo, é como se, quando o arquivo fosse carregado, o JS puxasse para o começo do código todas as funções que têm nome e já gravasse todas elas. Então não importa em que parte do código elas são chamadas, o JS já sabe o que elas fazem. 133 | 134 | Já as expressões (esse último caso que vimos) são anônimas, então o JS não sabe o que elas fazem até que chegue na linha certa. Na prática: 135 | 136 | ```js 137 | 138 | funcaoDeclarada() 139 | 140 | function funcaoDeclarada() { 141 | console.log('essa função já foi carregada!') 142 | } 143 | 144 | ``` 145 | 146 | Você pode tranquilamente chamar a função antes de declarar o que ela faz, pois o JS quando carregar o arquivo vai *primeiro* puxar pro topo as funções nomeadas, ler o que elas fazem e aí então executar o código. 147 | 148 | Já no caso das expressões de função: 149 | 150 | ```js 151 | expressaoDeFuncao() 152 | 153 | const expressaoDeFuncao = function() { 154 | console.log('será que funcionou?') 155 | } 156 | 157 | ``` 158 | Se você rodar o código como está, vai receber um erro do tipo `expressaoDeFuncao is not defined` ("expressaoDeFuncao não está definido") porque o JS não consegue chamar uma função antes de ler o que ela faz, e uma coisa está depois da outra. Troque as linhas de lugar e tudo volta a funcionar! 159 | 160 | ### Arrow Functions (função seta) 161 | 162 | Por fim, uma última forma (por enquanto!) de se escrever funções. Essa forma veio com as implementações mais recentes do JS, o tal ES6 ou JS2015 e é chamada de *arrow function*, por ser caracterizada pela `=>` (arrow, ou seta/flecha). 163 | 164 | Essa forma pode a princípio parecer um pouco estranha de escrever, mas você vai se acostumando! Comece pela forma que acha mais confortável. 165 | 166 | A *arrow function* é uma outra forma de se escrever somente **expressões de função**. 167 | 168 | O jeito tradicional de escrever: 169 | ```js 170 | const soma = function (num1, num2) { 171 | return num1 + num2 172 | } 173 | console.log(soma(1, 1)) //2 174 | ``` 175 | 176 | Utilizando *arrow function*: 177 | ```js 178 | const soma = (num1, num2) => num1 + num2 179 | console.log(soma(1, 1)) //2 180 | ``` 181 | 182 | Nessa versão: 183 | - não utilizamos a palavra-chave `function` 184 | - a seta `=>` que indica função vai *depois* dos (parâmetros) 185 | - como o código da função só tem uma linha, não precisamos abrir e fechar chaves `{}` e nem escrever `return` (fica implícito) 186 | 187 | Caso a função tenha mais de uma linha, aí sim precisamos abrir chaves e escrever `return`, mesmo usando a `=>`: 188 | ```js 189 | const imprimirSomaEPessoa = (num1, num2, nome) => { 190 | const resultadoSoma = num1 + num2 191 | return `resultado: ${resultadoSoma}, pessoa: ${nome}` 192 | } 193 | console.log(imprimirSomaEPessoa(1, 1, 'Helena')) 194 | ``` 195 | 196 | ### iife 197 | **IIFE (Immediately Invoked Function Expression), ou funções imediatas** 198 | 199 | É uma forma de declarar uma função e já executá-la em seguida, sem precisar chamar a função em uma outra linha de código. Pode funcionar tanto com expressões ou com funções declaradas. Basta envolver toda a função com parênteses e incluir parênteses vazios no final: 200 | 201 | ```js 202 | const imprime = (function () { 203 | let nome = 'Helena' 204 | return nome; 205 | })() 206 | console.log(imprime) 207 | ``` 208 | Nesse exemplo, a variável `imprime` não guarda a função e sim *somente seu resultado*. O que está sendo exibido no console em `console.log(imprime)` é justamente esse resultado. 209 | 210 | Vamos ver outro exemplo: 211 | ```js 212 | (function imprime() { 213 | let nome = 'Helena' 214 | console.log(nome) 215 | })() 216 | ``` 217 | 218 | Também vai funcionar com funções nomeadas, mas o normal é utilizar com *expressões*. 219 | Você também pode escrever com os parênteses vazios para dentro, dessa forma. 220 | ```js 221 | const imprime = (function () { 222 | let nome = 'Helena' 223 | return nome; 224 | }()) 225 | ``` 226 | 227 | ### Dicas 228 | Algumas dicas de funções que você pode levar pra vida: 229 | 230 | Listamos alguns princípios que te vão te ajudar a escrever funções melhores: 231 | 232 | * **Don't Repeat Yourself (DRY)**: É muito comum que a gente identifique um padrão que se repete ao longo de nosso código. 233 | 234 | Uma vez identificado um padrão - por exemplo, se você escreveu dois pedaços de código muito parecidos, é hora de escrever uma função que faça um "modelo" do padrão encontrado para que seja reutilizado facilmente. 235 | 236 | * **Do One Thing (DOT)**: Cada função deve fazer somente uma coisa e fazê-la o melhor possível. Seguindo este princípio, você escreverá funções mais reutilizáveis, legíveis e fáceis de debugar. 237 | 238 | * **Keep It Simple Stupid (KISS)**: Se as funções devem fazer somente uma coisa, quanto mais claro e mais simples, melhor. Nem sempre é fácil fazer isso, especialmente quando estamos começando. Praticar sempre! 239 | 240 | * **Less Is More**: Para serem o mais legíveis possível e reduzir a 241 | tentação de fazer mais de uma coisa, as funções devem ser tão pequenas quanto for possível. Se a função fica muito longa, é melhor considerar separá-la. 242 | 243 | ### Links 244 | 245 | Alguns links e referências. 246 | Esses links têm bastante conteúdo, vá se familiarizando aos pouquinhos! 247 | 248 | - [Funções](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Fun%C3%A7%C3%B5es) no MDN 249 | - [Vários exemplos](https://braziljs.org/artigos/funcoes-em-javascript/) de funções no site da BrazilJS. Algumas informações são específicas do JS no front-end, então não se preocupe se tiver muita coisa desconhecida! 250 | - [Capítulo inteiro de funções](https://braziljs.github.io/eloquente-javascript/chapters/funcoes/) do livro JavaScript Eloquente 251 | 252 | 253 | *** 254 | 255 | ## Escopos 256 | 257 | Escopo é como chamamos o contexto onde as coisas acontecem no código. Ou seja, onde cada trecho de código é lido, interpretado e pode ser acessado. 258 | 259 | Antes, no JavaScript podíamos apenas criar um novo escopo quando criavamos 260 | uma nova função. Mas desde a atulização do ES6 (ES2015) temos a `let` e a 261 | `const`, que introduziram o conceito de *escopo de bloco* no JavaScript. Um bloco de código é definido por estar entre chaves `{}`. 262 | 263 | O tema de escopo é complexo, então vamos ver um exemplo prático: 264 | 265 | ```js 266 | const exemplo = () => { 267 | let x = 1 268 | } 269 | exemplo() 270 | console.log(x) 271 | ``` 272 | 273 | Aqui, o escopo direto de `x` é a função `exemplo`. A variável `x` poderá ser acessada apenas dentro do bloco da função `exemplo`, mas não fora dela. Faça o teste com esse código, vai ver o erro `x is not defined`. Isso acontece porque `let x` foi criada *dentro do escopo de bloco da função `exemplo`* e só consegue ser acessada (ou visível) dentro da função - ou seja, entre as chaves `{}`. 274 | 275 | Vamos ver de novo: 276 | 277 | ```js 278 | const exemplo = () => { 279 | let x = 1 280 | console.log(x) 281 | } 282 | exemplo() 283 | ``` 284 | Agora sim. 285 | 286 | ### Nested Scopes (escopos aninhados) 287 | 288 | Se o escopo está aninhado dentro do escopo direto de uma variável, a 289 | variável será acessível a todos os escopos: 290 | 291 | ```js 292 | function textoExterno(texto) { 293 | console.log(texto) 294 | function textoInterno() { 295 | const frase = 'texto da função aninhada' 296 | console.log(frase) 297 | } 298 | textoInterno() 299 | } 300 | textoExterno('olar') 301 | ``` 302 | 303 | ### Sombreamento 304 | 305 | É possível declarar uma variável com o mesmo nome em um escopo interno 306 | de uma função, com isso o acesso à variável externa é bloqueado no escopo 307 | interno e todo os escopos aninhados dentro dela. Mudanças nas variáveis internas 308 | não afetam a variável externa, que é acessível fora do escopo interno. 309 | Exemplo: 310 | 311 | ```js 312 | let variavel = 'global'; 313 | function exemplo() { 314 | let variavel = 'local'; 315 | console.log(variavel); // local 316 | } 317 | exemplo(); 318 | console.log(variavel); // global 319 | ``` 320 | 321 | Dentro da função `exemplo`, a variável global `variavel` é "sombreada" pela variável local `variavel`. 322 | 323 | ### Declaração de variáveis no escopo local com `let` 324 | 325 | A "palavra" `let` declara uma variável de alcance local. Ela pode, opcionalmente, 326 | ser iniciada com algum valor e pode ser reatribuída (diferente de `const`). 327 | 328 | O alcance da `let` é local ao bloco, a declaração ou expressão onde se está 329 | usando. O que diferencia a palavra `let` da palavra `var` é que `var` não respeita o escopo de bloco e pode "escapar" quando menos esperamos (causando bugs). 330 | 331 | Alguns exemplos: 332 | 333 | ```js 334 | (function () { 335 | if (true) { 336 | let frase = 'Olar mundo'; 337 | } 338 | console.log(frase); 339 | })() 340 | ``` 341 | O exemplo acima vai dar erro, porque `let` só existe dentro do *escopo de bloco* do `if` (lembrando que um bloco de código é definido pelas `{}` e não precisa ser necessariamente uma função!). 342 | 343 | Se tentarmos novamente com `var`: 344 | ```js 345 | (function () { 346 | if (true) { 347 | var frase = 'Olar mundo'; 348 | } 349 | console.log(frase); 350 | })() 351 | ``` 352 | Agora a função roda normalmente e exibe a mensagem, pois `var`, ao contrário de `let` e `const` não liga muito pra escopo. 353 | 354 | Bom, então `var` é melhor né? **Não!** Nós normalmente não queremos esse comportamento, pois quanto mais "cercadas" as variáveis estiverem no código, menor a chance de comportamentos inesperados e de encontrarmos valores que não esperamos dentro das variáveis. 355 | 356 | Então, nada de `var`! As variáveis `let` e `const` surgiram justamente pra atender a essa necessidade de maior organização no código. 357 | 358 | ### Links 359 | 360 | - Uma geral sobre [escopos](https://pt.wikipedia.org/wiki/Escopo_(computa%C3%A7%C3%A3o)) na Wikipedia 361 | 362 | *** 363 | 364 | ## Loops ou laços de repetição 365 | 366 | Os *loops* são estruturas repetitivas, que permitem executar um código várias vezes, 367 | dependendo se uma condição **continua sendo** verdadeira. 368 | 369 | Imagine um programa que imprima todos os números pares do 1 ao 12. Uma maneira 370 | de escrevê-lo seria assim: 371 | 372 | ```js 373 | console.log(0) 374 | console.log(2) 375 | console.log(4) 376 | console.log(6) 377 | console.log(8) 378 | console.log(10) 379 | console.log(12) 380 | // … etcetera 381 | ``` 382 | 383 | Isso funciona, mas a ideia de escrever um programa é trabalhar menos, e não 384 | mais. E se fosse uma lista com 1000 números? Ficaria impossível. 385 | 386 | O que precisamos aqui é dar um jeito de repetir partes de código. Esta forma de **controle de fluxo** é chamada de loop. Os loops permitem voltar a certo ponto no programa em que estivemos antes e repetir qualquer operação a partir do estado em que estamos. 387 | 388 | ### while 389 | **Loop `while`** 390 | 391 | O loop mais simples é o loop `while` (que significa "enquanto" em português). Um 392 | loop `while` executa repetidamente uma série de instruções até que uma condição 393 | particular deixe de ser verdadeira. Ao escrever um loop `while`, você está 394 | dizendo: "Continue fazendo isto enquanto esta condição seja verdadeira. Pare 395 | quando a condição se tornar falsa." 396 | 397 | ```js 398 | while (condição) { 399 |  // Conjunto de sentenças, onde 400 | // se inclui algo que "muda" para 401 |  // que a condição eventualmente seja FALSA 402 | } 403 | ``` 404 | 405 | O loop executa o comando enquanto a condição produza um valor que seja `true`. Por isso é muito importante que o conjunto de comandos inclua algo que *"modifique"* para que a condição eventualmente seja falsa. Do contrário, vai gerar o que chamamos de "loop infinito", e vai dar ruim (travar seu terminal ou seu computador). 406 | 407 | Vamos voltar agora ao problema de imprimir todos os números pares do 1 ao 12, agora com `while`: 408 | 409 | ```js 410 | let numero = 0; 411 | while (numero <= 12) { 412 | console.log(numero); 413 | numero = numero + 2; 414 | } 415 | ``` 416 | Vamos ver o que acontece aqui: 417 | - Criamos uma variável `numero`, inicializamos com o valor 0, e a utilizamos na condição. Lendo a condição, podemos traduzir para "enquanto (while) o valor da variável `numero` for menor ou igual a 12. 418 | - O bloco do `while` inclui duas sentenças: a primeira imprime o número (com `console.log`) e a segunda incrementa `numero` em 2 (porque 419 | queremos imprimir só os pares). 420 | - A variável `numero` demonstra a forma em que uma variável pode dar seguimento ao progresso de um programa. Cada vez que o loop se repete, `numero` se incrementa em 2. Então, **no início de cada repetição**, o valor da variável `numero` é comparado com o número 12 para decidir se o programa fez todo o trabalho que deveria fazer. 421 | 422 | É importante entender que, se não modificamos o valor de `numero` com a segunda sentença, a condição `(numero <=12)` sempre será `true` e teremos um loop infinito. 423 | 424 | 425 | ### do 426 | **Loop `do`** 427 | 428 | O loop `do` é uma estrutura similar ao loop `while`. A diferença está em um só ponto: um loop `do` sempre executa o que está dentro do bloco *pelo menos uma vez* e começa a verificar se devería parar somente depois da primeira execução. 429 | Assim, a condição aparece depois do bloco do loop: 430 | 431 | ``` js 432 | let numero = 2 433 | do { 434 | console.log(numero) 435 | } while (numero < 2) 436 | ``` 437 | A palavra `do` significa "fazer" em inglês, então podemos ler o bloco acima dessa forma: "*faça* {o que está no bloco} *enquanto* a variável `numero` for menor que 2". Teoricamente esse bloco não deveria fazer nada, pois a variável `numero` já começa declarada com valor 2, mas como o loop `do` sempre roda o que está dentro do bloco pelo menos uma vez, vai imprimir `2` no console pelo menos uma vez antes de ver o que tem no "enquanto" (`while`). 438 | 439 | ### For 440 | 441 | O `for` é um loop mais completo e é bastante utilizado para situações mais complexas, quando precisamos fazer um controle mais "refinado" do que acontece em cada loop (ou iteração). 442 | 443 | Vamos ver a estrutura do `for` "clássico" com o mesmo caso de imprimir números pares de 1 a 12: 444 | 445 | ```js 446 | for (let numero = 0; numero <= 12; numero = numero + 2){ 447 | console.log(numero); 448 | } 449 | //0 450 | //2 451 | //etc 452 | ``` 453 | 454 | Hora de ver com calma o que acontece em cada parte desse código: 455 | - O primeiro trecho dentro do parênteses (`let numero = 0`) inicia o loop, normalmente definindo uma variável que vai ser alterada durante a execução do código. 456 | - O segundo trecho (`numero <= 12`) é a expressão que verifica se o loop tem que continuar. Cada vez que o JS chega ao fim do bloco `for` ele volta nesse trecho pra verificar se a condição ainda é `true`. 457 | - O último trecho atualiza o estado do loop antes de cada nova iteração. 458 | - Os três trechos dentro do parêntese devem sempre ser separados por ponto-e-vírgula (`;`). 459 | 460 | Toda vez que vamos pensar em um `for`, pensamos em três perguntas: 461 | 462 | 1. O que queremos que seja repetido a cada loop? 463 | 2. Que valor(es) queremos alterar a cada loop? 464 | 3. Quando queremos que o loop pare? 465 | 466 | Agora vamos ver um código que calcula 2^10 (2 exponencial 10), usando `for`: 467 | 468 | ```js 469 | let resultado = 1 470 | for (let contador = 0; contador < 10; contador++){ 471 | resultado = resultado * 2 472 | } 473 | console.log(resultado) 474 | // → 1024 475 | ``` 476 | 477 | A representação geral do loop `for` é a seguinte: 478 | 479 | ```js 480 | for (inicial; condição; incremento){ 481 | Bloco de código a executar 482 | } 483 | ``` 484 | 485 | O *inicial* (por exemplo: `let contador = 0`) se executa antes de que se 486 | inicie o loop. Geralmente se usa para criar uma variável que rastreia o número 487 | de vezes que foi executado o loop. 488 | 489 | A *condição* (`contador < 10`) é verificada antes de cada execução do bloco do loop. Se a condição é verdadeira, o bloco é executado; se é falsa, o loop se detém. Neste caso, o loop se deterá uma vez que counter já não seja inferior a 10. 490 | 491 | O *incremento* (`contador++`) é executado depois de cada execução do bloco do loop. Geralmente se utiliza para atualizar a variável do loop. No nosso exemplo, utilizamos para incrementar em 1 (usando o operador `++`) ao contador cada vez que se executa o loop. 492 | 493 | Lembrando que, se não damos ao loop uma condição de parada (por exemplo, incrementando a variável `contador` até que chegue ao valor de `10`) vamos cair no loop infinito! 494 | 495 | ### Break 496 | 497 | Fazer com que a condição do loop produza _false_ não é a única forma de finalizar um loop. Podemos usar a sentença especial `break`, utilizada no `switch`, que tem o efeito de sair imediatamente do loop. 498 | 499 | Vamos usar o `break` para encontrar o primeiro número que é maior ou igual a 500 | 20 e divisível por 7. 501 | 502 | ```js 503 | for (let numAtual = 20; ; numAtual++) { 504 | if (numAtual % 7 === 0) { 505 | console.log(numAtual); 506 | break 507 | } 508 | } 509 | // → 21 510 | ``` 511 | 512 | Usar o operador de resto ou módulo (%) é uma forma fácil de provar se o número é divisível por outro. Se for, o resto da divisão é zero. 513 | 514 | O `for` neste exemplo não tem a parte que verifica se o loop deve terminar. Isso significa que o loop não vai parar até que a sentença `break` que está dentro seja executada. 515 | 516 | Como já estamos aprendendo, se você deixasse fora essa sentença `break` ou 517 | acidentalmente escrevesse uma condição que sempre produza `true`, o seu programa ficaria travado em um loop infinito. 518 | 519 | A palavra chave `continue` é parecida com o `break` pois influencia o progresso do loop. Quando `continue` é lido no bloco de um loop, o controle sai do bloco do loop imediatamente e continua na próxima iteração do loop. 520 | 521 | ### Diferenças entre `for` e `while` 522 | 523 | Resumidamente, usamos o `for` quando sabemos quantas repetições vão ser 524 | realizadas e o `while` quando não sabemos. 525 | 526 | Por exemplo, se queremos dar o comando específico "gire as pás do ventilador 10 vezes", você já sabe que vamos girar o ventilador 10 vezes, então pode usar o `for`. 527 | 528 | Mas, se queremos dar uma instrução do tipo "enquanto estiver calor gire as pás do ventilador", não sabemos quantas vezes vamos girar o ventilador até a temperatura baixar, então nesse caso é melhor usar o `while`. 529 | 530 | ### Links 531 | 532 | - [Laços e iterações](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Lacos_e_iteracoes) no MDN 533 | - [For](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/for) no MDN 534 | - Lista de exercícios do [W#Schools](https://www.w3schools.com/js/exercise_js.asp?) 535 | 536 | *** 537 | 538 | ## Arrays 539 | 540 | O que acontece quando precisamos trabalhar com várias informações? 541 | Por exemplo, por enquanto estamos fazendo cálculos ou operações com poucos dados, então podemos fazer: 542 | ```js 543 | let num1 = 3 544 | let num2 = 45 545 | let num3 = 12 546 | console.log(num1 + num2 + num3) 547 | ``` 548 | 549 | Mas na vida real não costuma ser assim. E se nosso sistema tivesse que imprimir o valor total de uma compra de 100 ítens? 550 | Para isso usamos estruturas de dados, e a array é uma delas: uma array é uma **lista ordenada de dados**. Usando arrays, podemos guardar e também manipular uma quantidade qualquer de dados que estão guardados em uma única variável. 551 | 552 | O caso acima, então, ficaria da seguinte forma: 553 | ```js 554 | const numeros = [3, 45, 12] 555 | ``` 556 | 557 | A array é caracterizada pelos colchetes `[]`, e todos os dados que vão dentro delas são separados por vírgulas `,`. Vamos ver por partes: 558 | - Os colchetes `[]` indicam onde a array começa e termina. 559 | - Todos os dados que estão dentro da array devem ser separados por vírgula `,`. 560 | - Cada posição dentro da array (chamamos essas posições de *índices* - guarde esse nome!) é fixa e numerada, começando em zero. 561 | 562 | Como assim? 563 | A array é uma lista *ordenada*, isso significa que cada dado que está dentro dela ocupa uma determinada posição. Assim: 564 | 565 | ```js 566 | // índice 0 1 2 3 4 5 6 7 8 9 567 | const numeros = [3, 45, 12, 456, 656, 3, 55, 2, 6, 888] 568 | ``` 569 | 570 | Então podemos dizer que o número 12 está no **índice 2 da array `numeros`**. É muito importante lembrar sempre que a **a contagem começa a partir do índice zero**! 571 | 572 | Então, se quisermos acessar determinado dado que está dentro da array, devemos dizer em qual índice ele se encontra, usando os colchetes para informar o número do índice: 573 | ```js 574 | console.log(numeros[2]) // 12 575 | ``` 576 | 577 | Para saber quantos elementos (ou seja, quantos dados separados por vírgulas) temos em uma array, usamos `.length`: 578 | ```js 579 | console.log(numeros.length) //10 580 | ``` 581 | Ou seja, a array `numeros` tem 10 elementos, e para cada um é atribuído um *índice* que vai de 0 a 9. Cuidado para não se confundir ;) 582 | Você talvez tenha se perguntado por que `.length`, que usamos para ver qual a quantidade de caracteres em uma string, também funcionou na array. É porque, "por baixo dos panos", dados do tipo string entram na memória do computador da seguinte forma: 583 | ```js 584 | const palavraString = "banana" // ['b', 'a', 'n', 'a', 'n', 'a'] 585 | ``` 586 | 587 | Ou seja, para o JavaScript (e também as outras linguagens) uma string nada mais é do que uma array de caracteres. 588 | Faça o teste! 589 | ```js 590 | const x = 'banana' 591 | console.log(x[2]) //'n' 592 | ``` 593 | 594 | Finalizando por enquanto, vamos ver duas características de arrays que são **específicas do JavaScript**: 595 | 596 | 1. Cada array pode conter dados de diferentes tipos em cada índice. Por exemplo: 597 | ```js 598 | const arrayMista = [1, "banana", true, {chave: "valor"}, [1, true, "gatinho"], 55.6] 599 | ``` 600 | Essa é uma particularidade do JavaScript. As linguagens de programação normalmente só permitem arrays do mesmo tipo de dado, ou seja: 601 | ```js 602 | const arrayNums = [1, 4, 73, 55, 43] 603 | const arrayStrings = ["banana", "gatinho", "olar"] 604 | const arrayBool = [true, true, false, true, false] 605 | const arrayObj = [{chave: "valor"}, {chave: "valor"}, {chave: "valor"}] 606 | ``` 607 | 608 | 2. O comprimento da array (ou seja, a quantidade de elementos que tem dentro) é calculado dinamicamente e cresce automaticamente. Ou seja, diferente de outras linguagens, quando criamos uma array com JavaScript não precisamos dizer quantos elementos ela terá e podemos adicionar elementos dentro de uma array a qualquer hora, indefinidamente (enquanto a memória aguentar!). 609 | 610 | Por enquanto é só por esta aula. Na próxima veremos como utilizar e modificar arrays. 611 | -------------------------------------------------------------------------------- /arrays-objetos-metodos/readme.md: -------------------------------------------------------------------------------- 1 | # Arrays, objetos e métodos 2 | 3 | Nessa aula veremos como trabalhar com quantidades maiores de dados ao mesmo tempo, utilizando estruturas que chamamos de arrays e objetos. 4 | 5 | [Arrays](##-Arrays) 6 | * [Alterando arrays](###-Alterando-arrays) 7 | * [Iterando arrays](###-Iterando-arrays) 8 | * [O que é protótipo](###-O-que-é-protótipo) 9 | * [Métodos comuns de array](###-Métodos-comuns-de-array) 10 | 11 | [Objetos](##-Objetos) 12 | * [Acessando informações de um objeto](###-Acessando-informações-de-um-objeto) 13 | * [Criando ou alterando um objeto](###-Criando-ou-alterando-um-objeto) 14 | * [Métodos](###-Métodos) 15 | 16 | [Manipulando arrays e objetos](##-Manipulando-arrays-e-objetos) 17 | * [`for in` e `for of`](###-For...-in-e-for...-of) 18 | * [`filter`, `map` e `forEach`](###-`filter`,-`map`,-`forEach`) 19 | - [`filter`](###-`.filter()`) 20 | - [`map`](###-`.map()`) 21 | - [`forEach`](###-`.forEach()`) 22 | * [Outros métodos](###-Outros-métodos) 23 | * [Links](###-Links) 24 | 25 | [Onde fazer exercícios](##-Links-de-exercícios) 26 | *** 27 | 28 | ## Arrays 29 | 30 | O que acontece quando precisamos trabalhar com várias informações? 31 | Por exemplo, por enquanto estamos fazendo cálculos ou operações com poucos dados, então podemos fazer: 32 | ```js 33 | let num1 = 3 34 | let num2 = 45 35 | let num3 = 12 36 | console.log(num1 + num2 + num3) //60 37 | ``` 38 | 39 | Mas na vida real não costuma ser assim. E se nosso sistema tivesse que imprimir o valor total de uma compra de 100 ítens? 40 | Para isso usamos estruturas de dados, e a array é uma delas: uma array é uma **lista ordenada de dados**, também chamada de **vetor**. Usando arrays, podemos guardar e também manipular uma quantidade qualquer de dados que estão guardados em uma única variável. 41 | 42 | O caso acima, então, ficaria da seguinte forma: 43 | ```js 44 | const numeros = [3, 45, 12] 45 | ``` 46 | 47 | A array é caracterizada pelos colchetes `[]`, e todos os dados que vão dentro delas são separados por vírgulas `,`. Vamos ver por partes: 48 | - Os colchetes `[]` indicam onde a array começa e termina. 49 | - Todos os dados que estão dentro da array devem ser separados por vírgula `,`. 50 | - Cada posição dentro da array (chamamos essas posições de *índices* - guarde esse nome!) é fixa e numerada, começando em zero. 51 | 52 | Como assim? 53 | A array é uma lista *ordenada*, isso significa que cada dado que está dentro dela ocupa uma determinada posição. Assim: 54 | 55 | ```js 56 | // índice 0 1 2 3 4 5 6 7 8 9 57 | const numeros = [3, 45, 12, 456, 656, 3, 55, 2, 6, 888] 58 | ``` 59 | 60 | Então podemos dizer que o número 12 está no **índice 2 da array `numeros`**. É muito importante lembrar sempre que a **a contagem começa a partir do índice zero**! 61 | 62 | Então, se quisermos acessar determinado dado que está dentro da array, devemos dizer em qual índice ele se encontra, usando os colchetes para informar o número do índice: 63 | ```js 64 | console.log(numeros[2]) // 12 65 | ``` 66 | 67 | Para saber quantos elementos (ou seja, quantos dados separados por vírgulas) temos em uma array, usamos `.length`: 68 | ```js 69 | console.log(numeros.length) //10 70 | ``` 71 | Ou seja, a array `numeros` tem 10 elementos, e para cada um é atribuído um *índice* que vai de 0 a 9. Cuidado para não se confundir ;) 72 | 73 | Você talvez tenha se perguntado por que `.length`, que usamos para ver qual a quantidade de caracteres em uma string, também funcionou na array. É porque, "por baixo dos panos", dados do tipo string entram na memória do computador da seguinte forma: 74 | ```js 75 | const palavraString = "banana" // ['b', 'a', 'n', 'a', 'n', 'a'] 76 | ``` 77 | 78 | Ou seja, para o JavaScript (e também as outras linguagens) uma string nada mais é do que uma array de caracteres. 79 | Faça o teste! 80 | ```js 81 | const fruta = 'banana' 82 | console.log(fruta[2]) // 'n' 83 | console.log(fruta[2] === 'n') // true 84 | console.log(fruta[4 - 2]) // 'n' (é possível usar o resultado de cálculos!) 85 | ``` 86 | 87 | Existem duas características de arrays que são **específicas do JavaScript**: 88 | 89 | 1. Cada array pode conter dados de diferentes tipos em cada índice. Por exemplo: 90 | ```js 91 | const arrayMista = [1, "banana", true, {chave: "valor"}, [1, true, "gatinho"], 55.6] 92 | ``` 93 | Essa é uma particularidade do JavaScript. As linguagens de programação normalmente só permitem arrays do mesmo tipo de dado, ou seja: 94 | ```js 95 | const arrayNums = [1, 4, 73, 55, 43] 96 | const arrayStrings = ["banana", "gatinho", "olar"] 97 | const arrayBool = [true, true, false, true, false] 98 | const arrayObj = [{chave: "valor"}, {chave: "valor"}, {chave: "valor"}] 99 | ``` 100 | 101 | 2. O comprimento da array (ou seja, a quantidade de elementos que tem dentro dela) é calculado dinamicamente e cresce automaticamente. Ou seja, diferente de outras linguagens, quando criamos uma array com JavaScript não precisamos dizer quantos elementos ela terá e podemos adicionar elementos dentro de uma array a qualquer hora, indefinidamente (enquanto a memória aguentar!). 102 | 103 | Vamos ver em seguida como fazer isso. 104 | 105 | ### Alterando arrays 106 | 107 | Podemos usar índices entre colchetes para definir/alterar/adicionar elementos a uma array. 108 | 109 | ```js 110 | const arrayNums = [1, 4, 73, 55, 43] 111 | 112 | // alterando num valor que já existe 113 | arrayNums[0] = 5 114 | console.log(arrayNums) // [ 5, 4, 73, 55, 43 ] 115 | 116 | //adicionando um novo valor em um novo índice 117 | arrayNums[5] = 13 118 | console.log(arrayNums) // [ 5, 4, 73, 55, 43, 13 ] 119 | ``` 120 | 121 | Podemos criar uma array vazia e definir cada elemento individualmente: 122 | 123 | ```js 124 | const listaNumeros = [] 125 | listaNumeros[0] = 2 126 | listaNumeros[1] = 3 127 | listaNumeros[2] = 5 128 | listaNumeros[3] = 7 129 | listaNumeros[4] = 11 130 | 131 | console.log(listaNumeros) // [ 2, 3, 5, 7, 11 ] 132 | ``` 133 | 134 | Uma array pode estar dentro de outra, chamamos isso de *array de duas dimensões*: 135 | 136 | ```js 137 | const per+guntas = [ 138 | ['Quanto é 2 + 2?', 4], // índice 0 139 | ['Qual é a capital do Brasil', 'Brasília'], // índice 1 140 | ['Recife é a capital de Pernambuco', true] // índice 2 141 | ]; 142 | 143 | console.log(perguntas[2][1]) //true 144 | ``` 145 | 146 | ### Iterando arrays 147 | 148 | Ok, é possível acessar dados de dentro de uma array através do índice, por exemplo o índice 2 em uma array qualquer: `console.log(nomeDaArray[2])`, ou adicionar um novo ítem criando um novo índice no fim de uma array qualquer de 5 ítens com `nomeDaArray[5] = "valor"`. Parece prático? Não muito. 149 | 150 | O que fazemos quando: 151 | 1. Não sabemos em que índice da array está o dados que procuramos? 152 | 2. Não sabemos o tamanho da array para podermos inserir algo criando um novo índice (caso contrário, o novo dado vai substituir o que já está na array)? 153 | 3. Temos que fazer uma mesma operação com mais de um ítem da array - por exemplo, validar uma lista de 100 números de cartão de crédito? 154 | 155 | Esses casos acima são os mais comuns no dia-a-dia. E para acessar dados de uma array, alterar e etc, temos que *iterar* através da array, ou seja, **fazer um loop que percorra todos os ítens**. 156 | 157 | ```js 158 | for ([início]; [condição]; [pós-iteração]) { 159 | // instruções 160 | } 161 | 162 | for (let i = 0; i < array.length; i++) { 163 | console.log(array[i]) 164 | } 165 | ``` 166 | 167 | Sim, o mesmo `for` que usamos para strings e números! O `for` é utilizado para que possamos acessar uma array e manipular de várias formas: pegar elementos, fazer cálculos com eles, montar outras arrays, etc. Vamos ver a sintaxe novamente com esse exemplo: 168 | 169 | ```js 170 | const arrayNumeros = [45, 76, 34, 87, 34, 6] 171 | 172 | for (let i = 0; i < arrayNumeros.length; i++) { 173 | console.log("índice: ", i, "elemento: ", arrayNumeros[i]) 174 | } 175 | // índice: 0 elemento: 45 176 | // índice: 1 elemento: 76 177 | // índice: 2 elemento: 34 178 | // índice: 3 elemento: 87 179 | // índice: 4 elemento: 34 180 | // índice: 5 elemento: 6 181 | ``` 182 | 183 | Alguns pontos importantes: 184 | 1. A condição do `for` usa `arrayNumeros.length` para pegar o tamanho da array (em quantidade de elementos) e passar esse valor como condição de parada. Ou seja, o loop vai ocorrer **enquanto o valor de `let i` for menor que o número de elementos da array**, no caso 6. É como escrever `i < 6`, mas agora não precisamos saber o tamanho da array! O JS se encarrega disso. 185 | 2. Quando começamos a estudar arrays, usamos `array[0]`, por exemplo, para acessar o primeiro elemento de dentro da array (ou seja, o elemento que está no índice 0). Ora, se estamos começando o loop em 0 (o valor que iniciamos com `let i = 0`), podemos acessar cada item de dentro da array, **pois a cada loop o JS vai substituir `arrayNumeros[i]` por `arrayNumeros[0]`, `arrayNumeros[1]`, `arrayNumeros[2]`, etc.** 186 | 187 | Vamos ver outro exemplo, para somar todos os números de uma array: 188 | 189 | ```js 190 | const arrayNumeros = [45, 76, 34, 87, 34, 6] 191 | let somaArray = 0 192 | 193 | for (let i = 0; i < arrayNumeros.length; i++) { 194 | somaArray += arrayNumeros[i] 195 | } 196 | 197 | console.log(somaArray) // 282 198 | ``` 199 | 200 | Agora vamos ver ainda mais coisas que podemos fazer com arrays. 201 | 202 | ### O que é protótipo 203 | 204 | Arrays em JavaScript são implementadas como objetos. Isso pode soar um pouco estranho mas, em JavaScript, quase todos os tipos de dados (number, string, array, etc) são implementados como objetos e, como tal, os valores desses tipos terão uma série de métodos e propriedades associados a eles. Tecnicamente, eles herdam esses métodos e propriedades de um protótipo. 205 | 206 | Neste curso, nós não vamos aprofundar o mecanismo de herança prototipal em JavaScript, mas precisamos ao menos saber que qualquer array em JavaScript é uma instância do construtor (constructor) `Array` e, portanto, herda todos os métodos e propriedades definidos em `Array.prototype`. 207 | 208 | Vamos ver agora o que são esses métodos. 209 | 210 | ### Métodos comuns de array 211 | 212 | Existem muitos métodos para manipular arrays, iterar, etc. Não se preocupe em memorizar a lista completa (não acredito que alguém saiba de cabeça), você vai se familiarizar com eles conforme o uso, aprendendo a tirar vantagem de seus benefícios. Lembre-se de que sempre há a [documentação oficial](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array) disponível. Faça uso dela, é a melhor referência. 213 | 214 | Alguns deles são: 215 | 216 | * para agregar e retirar elementos: `push`, `pop`, `shift`, `unshift`, `slice`, `splice` e `concat`. 217 | * para buscar elementos dentro da array: `indexOf`, `lastIndexOf`, `includes`, `find`, `findIndex` e `filter`. 218 | * para transformar arrays: `map`, `reduce`, `sort`, `reverse`, `split` e `join`. 219 | 220 | Vamos ver alguns em detalhe: 221 | 222 | #### `array.push()` 223 | 224 | O método `array.push()` recebe um valor, adiciona-o ao final da array e devolve o novo tamanho (ou comprimento). 225 | Vamos adicionar `1` a uma array que já existe. 226 | 227 | ```js 228 | let arrayNum = [0, 0, 0] 229 | console.log(arrayNum.length === 3) // true 230 | arrayNum.push(1) 231 | console.log(arrayNum) // [ 0, 0, 0, 1 ] 232 | ``` 233 | 234 | #### `array.pop()` 235 | 236 | Esse método não recebe nenhum parâmetro. Ele simplesmente extrai o último elemento da array e retorna esse elemento (modificando a array diretamente - *in place*). 237 | 238 | ```js 239 | const arrayStrings = ['banana', 'gatinho', 'socorro'] 240 | const elementoRetirado = arrayStrings.pop() 241 | console.log(elementoRetirado) // 'socorro' 242 | console.log(arrayStrings) // [ 'banana', 'gatinho' ] 243 | ``` 244 | 245 | #### `array.slice()` 246 | 247 | Esse método cria um nova array através de uma "cópia superficial" *(shallow copy)* de uma parte da array. Ele recebe dois parâmetros que indicam qual parte da array queremos copiar (sem incluir o elemento do segundo índice). *A array original não é modificada*. 248 | 249 | Execute os seguintes exemplos para ver como o método `slice()` se comporta. 250 | 251 | ```js 252 | const arrayOriginal = [3, 2, 1] 253 | 254 | //começando a cópia a partir do índice 0 até o fim da array 255 | console.log(arrayOriginal.slice(0)) // [ 3, 2, 1 ] 256 | //começando a cópia a partir do índice 1 até o fim da array 257 | console.log(arrayOriginal.slice(1)) // [ 2, 1 ] 258 | //começando a cópia a partir do índice 2 até o fim da array 259 | console.log(arrayOriginal.slice(2)) // [1] 260 | //começando a cópia a partir do último índice 261 | console.log(arrayOriginal.slice(-1)) // [1] 262 | //começando a cópia a partir do índice 0 e parando no índice 1 (sem incluir o 1) 263 | console.log(arrayOriginal.slice(0, 1)) // [3] 264 | //a array original não é modificada 265 | console.log(arrayOriginal) // [3, 2, 1] 266 | ``` 267 | 268 | Lembrando que a array original não é modificada! Você pode guardar o valor de retorno de `.slice()` em uma nova variável: 269 | ```js 270 | const novaArray = arrayOriginal.slice(1) 271 | console.log(novaArray) // [ 2, 1 ] 272 | ``` 273 | 274 | #### array.indexOf() 275 | 276 | Esse método recebe um valor e devolve o índice da array que contém esse valor, se ele for encontrado, ou -1 caso contrário. Esse método é usado com muita frequência para verificar se uma array contém um determinado valor (basta que o resultado seja diferente de -1). 277 | 278 | ```js 279 | const arrayStrings = ['banana', 'maçã', 'uva'] 280 | console.log(arrayStrings.indexOf('banana')) // 0 281 | console.log(arrayStrings.indexOf('fruta')) // -1 282 | ``` 283 | 284 | A lista completa de métodos e uma descrição do que eles fazem está na documentação do [MDN](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype). Está em português! 285 | 286 | Alguns métodos requerem mais linhas de código e precisam de mais informações do que outros, dependendo do que queremos fazer. Vamos ver alguns desses com mais detalhe logo mais, quando trabalharmos com **objetos**. 287 | 288 | *** 289 | 290 | ## Objetos 291 | 292 | Os objetos em JavaScript são muito similares ao arrays, mas com alguns diferenciais: 293 | 294 | 1. Como vimos, para acessar informações dentro de um array, nós usamos um número correspondente ao índice; isto é, a posição em que o valor está localizado. Os objetos, por outro lado, utilizam strings ao invés de números para acessar os diferentes elementos. Essas strings são chamadas de **chaves (keys) ou propriedades**, e os elementos para os quais eles apontam são chamados de **valores (values)**. Juntas, essas informações são chamadas de pares de chave-valor. 295 | 2. Como nos arrays é necessário o índice para acessar informações, é importante manter uma determinada ordem de seus valores. No caso dos pares de chave-valor, as informações podem estar em qualquer ordem. 296 | 297 | Enquanto os arrays são usados ​​principalmente para representar listas de várias coisas, os objetos costumam ser usados ​​para representar elementos simples, mas com várias características ou atributos. Por exemplo, se quiséssemos agrupar os nomes das alunas de uma turma de programação, por exemplo: 298 | 299 | ```js 300 | const arrayAlunas = ['Helena', 'Josélia', 'Melina', 'Carla'] 301 | ``` 302 | 303 | Ok, mas e se fosse preciso armazenar outras informações sobre cada aluna? É quando usamos objetos: 304 | 305 | ```js 306 | const aluna = { 307 | nome: 'Helena', 308 | turma: 'on7', 309 | email: 'h@h.com', 310 | celular: '(11) 999-999-999', 311 | pet: 'gato' 312 | } 313 | ``` 314 | 315 | Vamos ver a sintaxe dos objetos: 316 | - Cada objeto é definido por chaves `{}`, ao invés dos colchetes `[]` usados nas arrays. 317 | - Um objeto é composto por **pares de chave-valor**, escritos no formato `chave: valor` e separados por vírgula. A chave (por exemplo, nome) e fica à esquerda; o valor à direita. *Cada par de chave-valor é separado por uma vírgula*. 318 | 319 | Os valores podem ser dos mesmos tipos de dados que usamos até agora: 320 | 321 | ```js 322 | const pessoa = { 323 | nome: "Marcia", // string 324 | altura: 1.65, // float 325 | matriculada: true, // booleano 326 | turmas: ['front', 'ux'], // array 327 | contato: { // outro objeto! 328 | nome: "Maria", 329 | parentesco: "irmã", 330 | celular: "(11) 999-999-999" 331 | } 332 | } 333 | ``` 334 | 335 | ### Acessando informações de um objeto 336 | 337 | Podemos acessar os valores de um objeto de duas maneiras: 338 | 339 | 1. **Notação de colchetes []**, assim como fazemos com arrays. A única diferença é que, em vez de usar o índice (um número), usamos a chave (uma string). 340 | 2. **Notação de ponto .** O segundo é usando o ponto (.) com o nome da chave imediatamente depois, sem aspas. 341 | 342 | Quando usamos um ou outro? 343 | 344 | O ponto é o formato mais usado, da seguinte forma: 345 | ```js 346 | console.log(pessoa.nome) // 'Marcia' 347 | console.log(pessoa.turmas) // [ 'front', 'ux' ] 348 | console.log(pessoa.turmas[0]) // 'front' 349 | console.log(pessoa.contato.parentesco) // 'irmã' 350 | ``` 351 | 352 | Para acessarmos os mesmos dados, usando colchetes: 353 | 354 | ```js 355 | console.log(pessoa['nome']) // 'Marcia' 356 | console.log(pessoa['turmas']) // [ 'front', 'ux' ] 357 | console.log(pessoa['turmas'][0]) // 'front' 358 | console.log(pessoa['contato']['parentesco']) // 'irmã' 359 | ``` 360 | 361 | Então pra que os colchetes, se a notação de ponto é mais fácil de escrever e ler? 362 | A notação de colchetes faz uma coisa que a de ponto não faz: aceita variáveis. 363 | Vamos ver: 364 | 365 | ```js 366 | const nomeDaChave = "nome" 367 | console.log( pessoa[nomeDaChave] ) // 'Marcia' 368 | console.log( pessoa.nomeDaChave ) // undefined 369 | ``` 370 | 371 | Pode parecer estranho agora, mas isso é muito útil quando precisamos escrever um código que aceite receber chaves diferentes ou não temos como saber qual chave precisamos no momento. *Nesse caso não usamos aspas!* 372 | 373 | ### Criando ou alterando um objeto 374 | 375 | Assim como com arrays, podemos adicionar ou alterar os elementos de um objeto usando os colchetes e chaves ou notação de ponto. 376 | Vamos ver um exemplo, começando com um objeto vazio: 377 | 378 | ``` js 379 | const pessoa = {} // objeto vazio 380 | 381 | pessoa['nome'] = 'Lúcia' // criando um par de chave-valor nome: 'Lúcia' 382 | pessoa['idade'] = 28 // criando um par de chave-valor idade: 28 383 | 384 | pessoa.cursos = ['front', 'ux'] // criando também, mas com notação de ponto 385 | pessoa.matriculada = true // idem! 386 | 387 | console.log(pessoa) 388 | // { 389 | // nome: 'Lúcia', 390 | // idade: 28, 391 | // cursos: [ 'front', 'ux' ], 392 | // matriculada: true 393 | // } 394 | 395 | pessoa.matriculada = false 396 | // { 397 | // nome: 'Lúcia', 398 | // idade: 28, 399 | // cursos: [ 'front', 'ux' ], 400 | // matriculada: false 401 | // } 402 | ``` 403 | 404 | Com a sintaxe acima conseguimos criar novos pares de chave-valor em um objeto; se o par já existir, o valor é substituído. 405 | 406 | ### Métodos 407 | 408 | Quando pensamos em objetos, pensamos em *representações* da realidade. Por exemplo, um livro tem diversas características: título, autoria, número de páginas, etc. Então pode ser *representado* da seguinte forma: 409 | 410 | ```js 411 | const objLivro = { 412 | titulo: "Dom Casmurro", 413 | autoria: "Machado de Assis", 414 | paginas: 200, 415 | ehPessoaViva: false 416 | } 417 | ``` 418 | 419 | Mas, além de listar propriedades, um objeto também pode representar comportamentos. Um objeto pode ter dentro dele *funções* que trazem comportamentos, interagem com as propriedades, fazem cálculos, etc. **Estas funções (chamadas com objetos através da notação `objeto.funcao()`) são chamadas de MÉTODOS**. O JS traz uma série de métodos "prontos" que utilizamos no dia-a-dia, e cada biblioteca que usamos tem seus próprios métodos - isso está ligado ao fato de que praticamente tudo em JS é objeto, mas não vamos entrar em detalhes sobre isso agora. Podemos criar nossos próprios métodos dentro de objetos: 420 | 421 | ```js 422 | const objGato = { 423 | nome: "Satanás", 424 | pelagem: "vaquinha", 425 | peso: 6.6, 426 | miar: function() { 427 | return `O gato ${this.nome} diz: miau` 428 | } 429 | } 430 | 431 | console.log(objGato.miar()) 432 | ``` 433 | O que é o `this`? Vamos deixar para vocês pesquisarem ;) 434 | 435 | Agora vamos ver o mesmo código, utilizando *arrow functions*. Observe as diferenças: 436 | 437 | ```js 438 | const objGato = { 439 | nome: "Satanás", 440 | pelagem: "vaquinha", 441 | peso: 6.6, 442 | miar: () => `O gato ${objGato.nome} diz: miau` 443 | } 444 | 445 | console.log(objGato.miar()) 446 | ``` 447 | 448 | Assim como qualquer função e como os métodos comuns do JS que já usamos, esses métodos que criamos também podem receber parâmetros: 449 | 450 | ```js 451 | const objGato = { 452 | nome: "Satanás", 453 | pelagem: "vaquinha", 454 | peso: 6.6, 455 | miar: function(miado) { 456 | return `O gato ${this.nome} diz: ${miado}` 457 | } 458 | } 459 | 460 | console.log(objGato.miar("minhauuuu")) 461 | ``` 462 | 463 | ## Manipulando arrays e objetos 464 | 465 | Essas duas estruturas são muito comuns quando lidamos com dados: 466 | 467 | ```js 468 | // uma propriedade (cursos) tendo uma array como valor 469 | { 470 | nome: "Helena", 471 | cursos: ["front", "back", "ux"] 472 | } 473 | ``` 474 | ```js 475 | // uma array com vários objetos dentro 476 | [ 477 | { nome: "Helena", matriculada: true }, // índice 0 478 | { nome: "Solange", matriculada: true }, // índice 1 479 | { nome: "Ana", matriculada: false } // índice 2 480 | ] 481 | ``` 482 | 483 | Vamos criar uma estrutura um pouco mais completa para testar: 484 | 485 | ```js 486 | const helena = { 487 | id: 345, 488 | nome: 'Helena', 489 | cursos: ['front', 'back'], 490 | matriculada: true 491 | } 492 | 493 | const joana = { 494 | id: 656, 495 | nome: 'Joana', 496 | cursos: ['front'], 497 | matriculada: true 498 | } 499 | 500 | const marcia = { 501 | id: 234, 502 | nome: 'Marcia', 503 | cursos: ['back', 'ux'], 504 | matriculada: false 505 | } 506 | 507 | const alunas = [helena, joana, marcia] // uma array com 3 objetos! 508 | ``` 509 | 510 | Usando novamente o `for`, podemos acessar cada um dos objetos e suas propriedades: 511 | 512 | ```js 513 | for (i = 0; i < alunas.length; i++) { 514 | console.log(alunas[i].nome) 515 | } 516 | 517 | // Helena 518 | // Joana 519 | // Marcia 520 | ``` 521 | 522 | Para acessar uma array de cursos dentro de outra array de alunas? Podemos fazer um for dentro de outro: 523 | 524 | ```js 525 | for (i = 0; i < alunas.length; i++) { 526 | for (j = 0; j < alunas[i].cursos.length; j++) { 527 | console.log(alunas[i].cursos[j]) 528 | } 529 | } 530 | // front 531 | // back 532 | // front 533 | // back 534 | // ux 535 | ``` 536 | 537 | Faça alguns testes acessar as informações que quiser, imprimir no console, etc. 538 | 539 | ### For... in e for... of 540 | 541 | Também podemos utilizar outros `for`, parecidos como "clássico", mas que têm uma sintaxe um pouco mais legível para nós. 542 | Para iterarmos arrays, utilizamos o **for... of**: 543 | 544 | ```js 545 | for (aluna of alunas) { 546 | if (aluna.matriculada) { 547 | console.log(aluna.nome) 548 | } 549 | } 550 | // Helena 551 | // Joana 552 | 553 | for (aluna of alunas) { 554 | console.log(`A aluna ${aluna.nome} cursa:`) 555 | for (curso of aluna.cursos) { 556 | console.log(curso) 557 | } 558 | } 559 | // A aluna Helena cursa: 560 | // front 561 | // back 562 | // A aluna Joana cursa: 563 | // front 564 | // A aluna Marcia cursa: 565 | // back 566 | // ux 567 | ``` 568 | 569 | Revendo a sintaxe: 570 | - `aluna` está fazendo o papel da variável `let i` que usamos para iniciar o for e `alunas` é o nome da array que vamos trabalhar. 571 | - Nesse for, não precisamos mais dizer quando o loop tem que parar: ele faz isso automaticamente a partir do tamanho da array `alunas`. 572 | - Também não precisamos dizer ao JS o que fazer no final de cada iteração (o que fazíamos com `i++`, por exemplo). Ele vai passar para o próximo índice da array sozinho. 573 | 574 | Então por que não usamos somente esse for, ao invés do "clássico" que temos que escrever muito mais? Bom, o `for of` funciona bem quando temos essa relação de **uma array de objetos e arrays dentro de objetos**, já que esse for faz automaticamente o loop passando por todos os índices da array. Porém, se precisamos fazer algum cálculo onde temos que fazer um ajuste mais fino (por exemplo, se números crescentes ou decrescentes), ainda vamos precisar do clássico. 575 | 576 | E quando queremos iterar *objetos*? 577 | Uma das formas é parecida com o `for of`, porém o nome é `for in`: 578 | 579 | ```js 580 | const livro = { 581 | titulo: 'Quarto de Despejo', 582 | autoria: 'Carolina Maria de Jesus', 583 | paginas: 200, 584 | categoria: ['literatura brasileira', 'autoras mulheres', 'premiado'] 585 | } 586 | 587 | for (caracteristica in livro) { 588 | console.log(`chave: ${caracteristica}, valor: ${livro[caracteristica]}`) 589 | } 590 | 591 | // chave: titulo, valor: Quarto de Despejo 592 | // chave: autoria, valor: Carolina Maria de Jesus 593 | // chave: paginas, valor: 200 594 | // chave: categoria, valor: literatura brasileira,autoras mulheres,premiado 595 | ``` 596 | 597 | Aqui, `caracteristica` é o nome que damos para a variável que faz o papel de `let i` (ou seja, a variável que será iterada). O importante é ver como fazemos para acessar a chave e o valor do objeto: chamando apenas a variável (no caso, `caracteristicas`), o for traz as chaves, porém se queremos o *valor* das chaves, usamos a notação de colchetes como já fizemos antes: `livro[caracteristica]`. 598 | 599 | ### `filter`, `map`, `forEach` e `reduce` 600 | 601 | Já vimos vários métodos úteis, mas separamos estes pois sua sintaxe é um pouco diferente. 602 | 603 | * `filter()` filtra elementos e cria um novo array 604 | * `map()` mapeia a array, executa a instrução e devolve um novo array como resultado. 605 | * `forEach()` executa uma dada função em cada elemento de um array, sem retornar. 606 | * `reduce()` executa uma função redutora para cada ítem do array, com num único valor de retorno. 607 | 608 | 609 | #### `filter()` 610 | 611 | Usamos para trazer um subconjunto dos elementos da array, desde que cumpram uma certa condição. 612 | *O resultado é sempre uma nova array com os elementos filtrados (ou uma array vazia se não encontrar nada)* 613 | 614 | ```js 615 | const numeros = [34, 62, 7447, 764, 86, 657, 87, 9] 616 | 617 | const maioresQueCinquenta = numeros.filter(numero => numero > 50) 618 | console.log(maioresQueCinquenta) // [ 62, 7447, 764, 86, 657, 87 ] 619 | ``` 620 | 621 | Podemos usar o `.filter()` para fazer coisas mais complexas com uma array de objetos! Caso o filtro encontre o valor procurado em qualquer valor dentro do objeto, o objeto inteiro é copiado para dentro da nova array de resultados. 622 | 623 | ```js 624 | const pokemons = 625 | [ 626 | { id: 1, name: "Bulbasaur", type: [ "Grass", "Poison" ] }, 627 | { id: 2, name: "Ivysaur", type: [ "Grass", "Poison" ] }, 628 | { id: 4, name: "Charmander", type: [ "Fire" ] } 629 | ] 630 | 631 | const grassPokemonsFunction = pokemons 632 | .filter(function(pokemon) { 633 | pokemon.type[0] === "Grass" 634 | }) 635 | 636 | //a mesma coisa, com arrow function 637 | const grassPokemonsArrowFunction = pokemons 638 | .filter(pokemon => pokemon.type[0] === "Grass") 639 | 640 | console.log(grassPokemons) 641 | // [ { id: 1, name: 'Bulbasaur', type: [ 'Grass', 'Poison' ] }, 642 | // { id: 2, name: 'Ivysaur', type: [ 'Grass', 'Poison' ] } ] 643 | ``` 644 | 645 | Encontrou uma array dentro de outra array? Não tem problema, você pode iterar por ela também. A array interna, nesse exemplo, é o valor da propriedade `pokemon.type`. Vamos usar outro método em conjunto com o `.filter()` chamado `.includes()`, que verifica se determinado valor existe na array e retorna `true` ou `false`. 646 | 647 | ```js 648 | const grassPokemonsFunction = pokemons 649 | .filter(function(pokemon) { 650 | return pokemon.type.includes("Grass") === true 651 | }) 652 | 653 | //a mesma coisa, com arrow function 654 | const grassPokemonsArrowFunction = pokemons 655 | .filter(pokemon => pokemon.type.includes("Grass") === true) 656 | ``` 657 | 658 | O método `.filter()` aceita um segundo parâmetro, que é o índice que está sendo trabalhando a cada loop. Veja com mais detalhes abaixo, no `.map()`. 659 | 660 | #### `.map()` 661 | 662 | Com esse método podemos entrar em cada um dos elementos da array, coletando neste processo um valor de retorno para cada elemento visitado. O `.map()` é um dos métodos que mais usamos no dia-a-dia para percorrer arrays, medificá-las e formar novas arrays com os elementos que queremos. 663 | 664 | Por exemplo, para obtermos uma lista somente com os nomes dos Pokemóns. Lembrando que o retorno *sempre* será uma array com os resultados dentro! 665 | 666 | ```js 667 | const pokemons = 668 | [{ 669 | id: 1, 670 | name: "Bulbasaur", 671 | type: [ "Grass", "Poison" ], 672 | }, 673 | { 674 | id: 2, 675 | name: "Ivysaur", 676 | type: [ "Grass", "Poison" ], 677 | }, 678 | { 679 | id: 4, 680 | name: "Charmander", 681 | type: [ "Fire" ], 682 | }] 683 | 684 | 685 | const nomesPokemons = pokemons.map(function(pokemon) { 686 | return pokemon.name 687 | }) 688 | 689 | //a mesma coisa, com arrow function 690 | const nomesPokemonsArrow = pokemons.map(pokemon => pokemon.name) 691 | 692 | console.log(nomesPokemons) // [ 'Bulbasaur', 'Ivysaur', 'Charmander' ] 693 | console.log(nomesPokemonsArrow) // [ 'Bulbasaur', 'Ivysaur', 'Charmander' ] 694 | ``` 695 | 696 | E quando precisamos trabalhar com o índice de uma array? O `.map()` também aceita um segundo parâmetro, onde podemos receber o índice da array que está sendo trabalhado! 697 | 698 | ```js 699 | const arr = [54, 65, 45, 56, 76] 700 | 701 | const multiplicaIndicesPares = arr.map((numero, indice) => { 702 | if (indice % 2 === 0) { 703 | return numero * 2 704 | } 705 | return numero 706 | }) 707 | 708 | console.log(multiplicaIndicesPares) 709 | ``` 710 | 711 | #### `forEach()` 712 | 713 | "For each" significa, em inglês, "para cada". No contexto, esse método significa que "*para cada* elemento da array, faça X". 714 | Importante: *Ao contrário do map, o forEach não retorna uma array com os resultados!* Ele não retorna nenhum dado, apenas percorre a array e faz o que for pedido no código. 715 | 716 | Continuando com os Pokémons: 717 | 718 | ```js 719 | let listaNomes = '' 720 | const nomesPokemons = pokemons.forEach(function(pokemon) { 721 | listaNomes += `O pokemón ${pokemon.name} tem id ${pokemon.id}\n` 722 | }) 723 | console.log(listaNomes) 724 | // O pokemón Bulbasaur tem id 1 725 | // O pokemón Ivysaur tem id 2 726 | // O pokemón Charmander tem id 4 727 | 728 | //a mesma coisa, com arrow function 729 | let outraListaNomes = '' 730 | const nomesPokemonsArrow = pokemons.forEach(pokemon => outraListaNomes += `O pokemón ${pokemon.name} tem id ${pokemon.id}\n`) 731 | console.log(outraListaNomes) 732 | // O pokemón Bulbasaur tem id 1 733 | // O pokemón Ivysaur tem id 2 734 | // O pokemón Charmander tem id 4 735 | ``` 736 | 737 | O `forEach()` também aceita um segundo parâmetro para pegarmos os índices que estão sendo trabalhados. 738 | 739 | ### Outros métodos 740 | 741 | Não vamos abordar aqui, mas você pode pesquisar mais sobre eles: 742 | 743 | - `array.reduce()`: um método que percorre a array e reduz valores a um único número. 744 | - `Object.keys(obj)` / `Object.values(obj)` / `Object.entries(obj)`: Esses métodos retornam uma array com todas as chaves/valores/pares de propriedades próprios de um objeto. 745 | - `Object.getOwnPropertyNames(obj)`: Esse método retorna um array contendo todos os nomes de propriedades próprios (enumeráveis ou não) de um objeto. 746 | 747 | ### Links 748 | 749 | - [Estruturas de dados](http://braziljs.github.io/eloquente-javascript/chapters/estrutura-de-dados/) no livro JavaScript Eloquente 750 | 751 | ## Links de exercícios 752 | 753 | - Para começar: Lista de exercícios de JavaScript do [W3Schools](https://www.w3schools.com/js/js_exercises.asp). Vai desde os conceitos mais básicos como variáveis. 754 | 755 | - Uma lista com mais de [100 exercícios](https://repl.it/community/classrooms/20690) de JS que vão de funções e variáveis até objetos e arrays (em inglês). Precisa criar uma conta no serviço Repl.it para fazer, salvar e testar as respostas. 756 | 757 | - [HackerRank](https://www.hackerrank.com/) - muitas empresas usam os testes desse site em vagas. 758 | 759 | - [URI](https://www.urionlinejudge.com.br/judge/pt/) - testes de programação e matemática de diversos níveis. 760 | 761 | --------------------------------------------------------------------------------