roger-melo-treinamentos / curso-de-js-roger-melo

Repositório de informações do CJRM
491 stars 170 forks source link

Resumo da Aula 01 da etapa 08 #3153

Closed ghostnetrn closed 2 years ago

ghostnetrn commented 2 years ago

Fazer a cópia de um objeto

const obj = {
  prop1: 'a',
  prop2: 'b',
  prop3: null,
  prop4: true,
  prop5: false,
  prop6: [9, { x: 1, y: 2 }],
  prop7: 7,
  prop8: { a: 'x', b: 'y' },
}

const objCopy = { ...obj } // utilizar o spread operator. Com este método, todos os valores, inclusive os métodos, são clonados.

console.log(objCopy) // o objeto foi copiado

O spread operator, além de criar cópias (rasas) de objetos e arrays, também possibilita unir um ou mais objetos/arrays. Antigamente, a junção de dois ou mais arrays era feita com o método .concat(), enquanto que a junção de dois ou mais objetos era feita com Object.assign(), permitindo criar um novo array/objeto ou modificar um já existente para inserir os itens de outros. Já o spread operator necessariamente cria um novo array/objeto, com a vantagem de uma legibilidade mais limpa. O spread operator desencapsula o array/objeto, cujos itens devem ser armazenados então em um novo.

const arr1 = [ 1, 2, 3]
const arr2 = [ 4, 5, 6]
const newArr = arr1.concat(arr2) 
console.log(newArr)

const obj1 = {prop1: 1 , prop2: 2}
const obj2 = {prop3: 3 , prop4: 4}

const obj3 = Object.assign({}, obj1, obj2)
const obj3 = { ...obj1, ...obj2}

console.log(obj3)
Neste processo, também podemos inserir outros itens que não constem nos arrays/objetos preexistentes.
const newArr = [ 0 ,...arr1, 85.4 ,...arr2, 87.4]

Unindo Objetos e arrays

spread operator em array

// concat => criar uma cópia rasa.
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]

const newArr1 = [0, ...arr1, 1.5, ...arr2, 7, 8]

**spread operator em objeto** 
const obj1 = {prop1: 1, prop2: 2}
const obj2 = {prop3: 3, prop4: 4}

// feature antiga (Object.assign()) também faz cópia rasa
const obj3 = Object.assign({}, obj1, obj2)

// com spread operator (...) estamos criando um novo objeto
const obj4 = { ...obj1, ...obj2 } // técnica de mutabilidade

O spread operator serve tanto para copiar um objeto e array, como para juntar 2 objetos ou arrays diferentes.

const arr1 = [1, 2, 3] const arr2 = [4, 5, 6]

const newArray = [...arr1, ...arr2] // [1, 2, 3, 4, 5, 6] Se quisermos, pode ser inserido outros valores nesse array, spread operator não impede isso.

Antigamente para unir 2 objetos era usado o Object.assign(), que recebe no mínimo 2 argumentos, o primeiro é o objeto que vai receber as cópias das propriedades, os demais argumentos será do qual ou quais objetos que vamos copiar.

const obj1 = {prop1: 1, prop2: 2}
const obj2 = {prop3: 3, prop4: 4}

const obj3 = Object.assign({} ,obj1, obj2)
// {prop1: 1, prop2: 2, prop3: 3, prop4: 4}

//     Com spread Operator

const obj3 = {...obj1, ...obj2}
//  {prop1: 1, prop2: 2, prop3: 3, prop4: 4}

Map:

O método map é usado quando queremos gerar um novo array com a mesma quantidade de elementos do array original, mas aplicando alguma transformação em cada elemento dele. Essa transformação é aplicada através de uma função passada como argumento ao map e será executada para cada elemento do array original.

O mpa é invocado encadeando com o array original e a função que fará a transformação pode receber três parâmetros:

item: é o item que está sendo iterado (obrigatório) index: é a posição do item iterado no array original array: é o próprio array original. A função será executada para cada item do array e o valor retornado por ela será adicionado ao novo array que a função map irá retornar.

Filter:

O método filter funciona de maneira similar ao map, ele recebe uma função como argumento e essa função será executada para cada item do array. Mas ele serve para obter um novo array apenas com alguns elementos do array original.

Assim como no map, a função recebida como argumento pode receber três parâmetros:

item: é o item que está sendo iterado (obrigatório) index: é a posição do item iterado no array original array: é o próprio array original. O filter criará um novo array com os elementos do array que atenderem a uma condição especificada pela função recebida, por isso essa função deve sempre retornar um valor booleano: Sempre que ela retornar 'true' o item da iteração será adicionado ao novo array, sempre que retornar 'false' o item será ignorado. Se a função retornar 'false' em todas as iterações, o filter retornará um array vazio .

Reduce:

O reduce também recebe uma função ppor argumento para ser executada para cada elemento do array, no entanto, ela serve para quando queremos reduzir o array original em algum outro tipo de dado, não necessariamente outro array.

O reduce recebe dois argumentos:

A função que será executada para cada item do array Um valor inicial que será utilizada pela função na primeira iteração do reduce. A função pode receber quatro argumentos:

accumulator: um acumulador que guardará o valor retornado pela função a cada iteração, para que possa ser usado na próxima. item: é o item que está sendo iterado index: é a posição do item iterado no array original array: é o próprio array original. Accumulator e item são argumentos obrigatórios.

A função precisa retornar um valor a cada execução pois esse valor será implicitamente atribuído ao acumulador para a próxima iteração.

Apesar de não ser obrigatório uma boa prática atribuir um valor inicial, para ter uma representação do tipo de dado que o reduce irá retornar. Esse valor será recebido pelo accumulator na primeira iteração do reduce. Caso esse valor não seja especificado, o accumulator irá receber o primeiro elemento do array como valor inicial e item começará com o segundo elemento.

Exemplos

Vamos imaginar que a gente precisa obter desse array só os livros acima de 20 reais e a partir disso vamos gerar para todos os livros string informando o nome e o preço do livro em promoção. Para fazer isso iremos utilizar primeiro o filter(), pois assim iremos obter só os livros acima de 20 reais. Como precisamos gerar também para todos os livros uma string informando o nome e o preço do livro em promoção, vamos utilizar o map().

const books = [
  { name: 'Código Limpo', price: 30 },
  { name: 'O milagre da manhã', price: 5 },
  { name: 'Alice no País das Maravilhas', price: 10 },
  { name: 'Quem Pensa Enriquece', price: 50 },
  { name: 'O livro da ciência', price: 40 }
]

const booksOnSale = books
  .filter(({ price }) => price > 20)
  .map(({ name, price }) =>
    `O preço do livro "${name}" caiu para ${price} reais`)

console.log(booksOnSale)
// ['O preço do livro "Código Limpo" caiu para 30 reais', 
    'O preço do livro "Quem Pensa Enriquece" caiu para 50 reais',
    'O preço do livro "O livro da ciência" caiu para 40 reais']

Agora vamos receber um array com objetos com nome e preço, e iremos modificar apenas os preços que forem acima de 30, dando um desconto de 50%.

const products = [
  { name: 'Mouse Sem Fio', price: 30 },
  { name: 'Pen Drive', price: 25 },
  { name: 'Cartucho de Tinta', price: 50 },
  { name: 'Suporte Ergonômico para Notebook', price: 23 },
  { name: 'Repetidor de Sinal Wi-Fi', price: 44 }
]

const saleProducts = products.map( product => {
  if (product.price >= 30) {
    return { name: product.name, price: product.price / 2 }
  }

  return product
})

O encadeamento de métodos é um recurso muito prático para manipulação de dados em um array. Se tivermos, por exemplo, uma lista de diversos produtos com diversas marcas e preços e precisarmos alterar temporariamente alguns deles, podemos gerar uma nova lista com as informações alteradas, de “uma vez só”.

Assim, ao invés de primeiro filtrarmos o array original com filter() para obtermos a informação desejada e depois aplicarmos o map() para transformar o novo array gerado pelo método anterior, podemos encadear estes dois métodos, eliminando a necessidade de duas variáveis para armazenar cada novo array gerado.
Exemplo:

// sem encadeamento (dois arrays gerados e armazenados separadamente)
const arrayFiltrado = arrayOriginal.filter(funçãoCondicional)
const arrayFiltradoeModificado = arrayFiltrado.map(funçãoParaModificação)

// encadeando (armazenando um único array)
const arrayFiltradoEModificado = arrayOriginal
    .filter(funçãoCondicional)
    .map(funçãoParaModificação)
Onde:

arrayOriginal é o array tomado como base
arrayFiltrado é a constante que recebeu o novo array gerado pelo método filter() com base no arrayOriginal
arrayFiltradoEModificado é a constante que recebeu o novo array gerado após uso do filter() e map()
funcãoCondicional é a função que deve conter a condição a ser verificada no método filter()
funçãoParaModificação é a função que deve conter a expressão para inserir as modificações desejadas no novo array, por meio do método map()
Por convenção, cada método é deixado em uma nova linha, indentando os conteúdos, para melhor visualização do que está sendo feito no array.

MÉTODO MAP array.map(item => {}): cria um novo array iterando os itens do array original e retornando um novo array, portanto, o método map precisa SEMPRE retornar um valor.

MÉTODO FILTER array.filter(item => {}): semelhante ao método map, porém o retorno agora é somente true ou false. Se true (obedecendo à condição da função de callback), adiciona o item no novo array, se false, ignora.

METÓDO REDUCE array.reduce((accumulator,item) => {}, 0): reduz um array inteiro em outro tipo de dado, utiliza o acumulador como ponto de partida e de soma/qualquer outra alteração. O número 0 no final é a indicação explícita de qual número o accumulator vai iniciar, de outra forma, ele recebe o primeiro item do array.

o significado do sort e ordenar. e isso que ele faz, ele ira ordenar o elementos do array. O método sort() ordena os elementos do próprio array e retorna o array. A ordenação não é necessariamente estável. A ordenação padrão é de acordo com a pontuação de código unicode. A complexidade do tempo de execução ou a quantidade de memória utilizada pela ordenação não pode ser garantido e depende da implementação realizada.

Diferente do método map, filter e reduce o sort modifica o array original.

no caso de números o sort iria ordenar o números verificado apenas o primeiro indez do número por não.

//exemplo 1: ordenando strings

const names = ['Gian', 'Olga', 'Maria']

names.sort()

console.log(names)

//exemplo 2: ordenando números 

const score = [10,50,5,75,95,16,88]

score.sort((item1, item2) =>   item2 - item1)

console.log(score)

// Exemplo 3: ordenando objetos 

const theBigFamily = [
    { name: 'Lineu', score: 20 },
    { name: 'Nenê', score: 10 },
    { name: 'Tuco', score: 50 },
    { name: 'Bebel', score: 30 },
    { name: 'Agostinho', score: 70 }
  ]

// theBigFamily.sort((item1, item2) => {
//     if (item1.score > item2.score) {
//         return -1
//     } else if ( item1.score > item2.score){
//         return 1
//     }

//     return 0
// })

theBigFamily.sort((item1, item2) => item1.score - item2.score)

console.log(theBigFamily) // [
  { name: 'Agostinho', score: 70 },
  { name: 'Tuco', score: 50 },
  { name: 'Bebel', score: 30 },
  { name: 'Lineu', score: 20 },
  { name: 'Nenê', score: 10 }
]

APLICAÇÃO TO DO LIST

const formAddToDo = document.querySelector('.form-add-todo')
const todosContainer = document.querySelector('.todos-container')

formAddToDo.addEventListener('submit', event => {
  event.preventDefault()

  const inputValue = event.target.add.value.trim()

  if (inputValue.length) { // se o valor do campo input for preenchido. Evita campo vazio no input
    todosContainer.innerHTML += `
        <li class="list-group-item d-flex justify-content-between align-items-center">
          <span>${inputValue}</span>
          <i class="far fa-trash-alt delete"></i>
        </li>`
  }

  event.target.reset() // usado para resetar para o valor padrão dos campos do form
})
Roger-Melo commented 2 years ago

Boa @ghostnetrn, rumo à fluência! 🔥