Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Fiz de uma forma diferente

Fiz desta forma, porém não entendi porque deu certo, já que o .map deveria retornar uma cópia do array, e não atribuir ao array principal


function aplicarDesconto () 
{
    const desconto = 0.3;
    return livros.map((livro) => livro.preco = Math.round(livro.preco * (1 - desconto)));
}
2 respostas
solução!

Olá Gabriel, tudo bem?

Se entendi bem, você quer saber por que a função aplicarDesconto()está alterando os valores nos objetos do próprio array livros e não retornando um array com os valores alterados (aplicados o desconto) sem alterar o original, correto?

Bom, na verdade AMBAS as coisas estão acontecendo. Explico!

Vamos analisar esse trecho do seu código:

return livros.map((livro) => livro.preco = Math.round(livro.preco * (1 - desconto)));

Prestando bastante atenção aos comandos utilizados, vemos que a função callback usada no método .map() está calculando o desconto para cada livro e aplicando esse desconto à propriedade preco do objeto livro que está sendo analisado à cada chamada. Objetos em JavaScript são do tipo "referência", ou seja, quando o método .map() percorre cada um dos itens do array livros NÃO estamos tendo acesso a uma "cópia" desses objetos, mas sim, ao objeto em si por meio de sua referência em memória. Sendo assim, ao realizarmos qualquer modificação neste objeto, o estamos alterando diretamente e se estamos alterando o objeto "original" e ele está dentro de um array (no caso "livros") então estamos alterando de alguma forma o conteúdo desse array.

Então, quando executamos a atribuição livro.preco = Math.round(livro.preco * (1 - desconto)) estamos alterando cada um dos objetos livro presentes no array livros através de sua referência em memória e assim, alterando o conteúdo do próprio array e, de quebra, o método .map() ainda está retornando um array que contém apenas os preços dos livros existentes no array livros aplicados os descontos.

Para não alterarmos o conteúdo do array principal (o array livros) basta não atribuirmos o resultado do cálculo do desconto à propriedade preco de cada livro conforme o código abaixo:

// retorna um array apenas com os preços de cada livro aplicados o desconto, ex: [129.30, 79.90, 52.67]
// sem atribuí-los aos objetos "livro" analisados
return livros.map((livro) => Math.round(livro.preco * (1 - desconto))); 

Isso já resolveria o "problema" da modificação no array original.

Agora, se quisermos retornar um array totalmente novo com TODOS os objetos livro tendo seu preço atualizado com os descontos aplicados SEM ALTERAR o array original, teríamos que fazer uma cópia de cada objeto livro com o desconto aplicado ao preço (a cópia se faz necessária para que a mesma referência em memória não seja compartilhada entre eles, isto é, que o objeto DE FATO seja completamente novo contendo as mesmas informações do objeto livro que o originou). Isso pode ser alcançado com o código de exemplo abaixo:

// retorna um array com cópias de todos os objetos livro existentes no array livros
// porém com o desconto aplicado ao preço de cada um deles
return livros.map((livro) => {
    return {
        ...livro,
        preco: Math.round(livro.preco * (1 - desconto))
    };
});

Perceba que a função callback do método .map() retorna agora não o valor do preço aplicado o desconto somente, mas sim, um objeto completamente novo que contém a cópia das propriedades e valores de cada livro percorrido pelo método .map():

return {
    ...livro
}

Veja que usamos um operador chamado Spread Operator (...) para "espalhar" todos os valores e propriedades do objeto livro no novo objeto anônimo que estamos criando para representar esse livro ({ }).

Contudo, precisamos alterar a propriedade preco para que ela tenha o valor atualizado (aplicado o desconto) e não o valor original. Sendo assim, sobrescrevemos apenas a propriedade que queremos alterar desse objeto, atribuindo a ela o novo preço:

return {
    ...livro,
    preco: Math.round(livro.preco * (1 - desconto))
};

Assim, o map vai retornar um array que é uma CÓPIA EXATA do array livros, porém com todos os preços dos livros atualizados e isso sem alterar o array original.

Ufa... bastante coisa, né?!

Bom, espero que tenha ficado claro e que eu tenha conseguido sanar sua dúvida.

Qualquer coisa, estamos por aqui.

Att.

Muito obrigado! Tirou todas as minhas dúvidas sobre esse assunto.