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

[Dúvida] Modificando a descrição do objeto tarefas

Não ficou claro pra mim como que no button.onclick o js sabe exatamente qual objeto alterar se eu não especifiquei o índice dele dentro do array. É posivel ver dentro do console o índice de cada um, pois coloquei um console.log dentro do onclick para exibir o valor atual como teste.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

código completo

const btnAdicionarTarefa = document.querySelector('.app__button--add-task')
const formAdicionarTarefa = document.querySelector('.app__form-add-task')
const textArea = document.querySelector('.app__form-textarea')
const ulTarefas = document.querySelector('.app__section-task-list')


const tarefas = JSON.parse(localStorage.getItem('tarefas')) || []

function atualizarTarefas() {
    localStorage.setItem('tarefas', JSON.stringify(tarefas))
}

function criarElementoTarefa(tarefa) {
    const li = document.createElement('li')
    li.classList.add('app__section-task-list-item')

    const svg = document.createElement('svg')
    svg.innerHTML = `
        <svg class="app__section-task-icon-status" width="24" height="24" viewBox="0 0 24 24" fill="none"
            xmlns="http://www.w3.org/2000/svg">
            <circle cx="12" cy="12" r="12" fill="#FFF"></circle>
            <path d="M9 16.1719L19.5938 5.57812L21 6.98438L9 18.9844L3.42188 13.4062L4.82812 12L9 16.1719Z"
                fill="#01080E"></path>
        </svg>
    `
    const paragrafo = document.createElement('p')
    paragrafo.textContent = tarefa.descricao
    paragrafo.classList.add('app__section-task-list-item-description')

    const botao = document.createElement('button')
    botao.classList.add('app_button-edit')

    botao.onclick = () => {
        const novaDescricao = prompt("Qual será a nova descrição?")
        paragrafo.textContent = novaDescricao
        console.log(tarefa.descricao)
        tarefa.descricao = novaDescricao
        atualizarTarefas()
    }

    const imagemBotao = document.createElement('img')
    imagemBotao.setAttribute('src', '/imagens/edit.png')
    botao.append(imagemBotao)

    li.append(svg)
    li.append(paragrafo)
    li.append(botao)

    return li
}

btnAdicionarTarefa.addEventListener('click', () => {
    formAdicionarTarefa.classList.toggle('hidden')
    setTimeout(() => {
        textArea.classList.toggle('active')
    }, 50)
})

formAdicionarTarefa.addEventListener('submit', (event) => {
    event.preventDefault()
    const tarefa = {                                        
        descricao: textArea.value
    }

    tarefas.push(tarefa)
    const elementoTarefa = criarElementoTarefa(tarefa)
    ulTarefas.append(elementoTarefa)
    atualizarTarefas()
    textArea.value = ('')
    formAdicionarTarefa.classList.add('hidden')
})

tarefas.forEach(tarefa => {
    const elementoTarefa = criarElementoTarefa(tarefa)
    ulTarefas.append(elementoTarefa)

})

console.log(tarefas)
3 respostas

Então, olha só — quando a gente faz esse trecho aqui:

botao.onclick = () => {
    const novaDescricao = prompt("Qual será a nova descrição?")
    paragrafo.textContent = novaDescricao
    console.log(tarefa.descricao)
    tarefa.descricao = novaDescricao
    atualizarTarefas()
}

…o segredo é esse tarefa aí.

Esse tarefa não é um índice nem nada disso, mas sim a referência direta ao objeto que foi passado quando tu chamou criarElementoTarefa(tarefa). E isso aconteceu lá no forEach e no submit do form:

tarefas.forEach(tarefa => {
    const elementoTarefa = criarElementoTarefa(tarefa)

Ou seja: quando a gente chama criarElementoTarefa(tarefa), ele recebe aquele objeto mesmo que tá dentro do array tarefas. Então, dentro da função, o botão já tá com acesso a exatamente aquele objeto. É tipo quando tu pega um item da lista e passa ele pra outra função — continua sendo ele, não uma cópia.

Por isso, mesmo sem passar o índice ou mexer no array diretamente, ele sabe exatamente qual tarefa alterar: porque tá usando a referência original.

Se tu abrir o console, vai ver que os logs batem certinho com o conteúdo do array, mesmo sem índice.

Se quiser ver o índice também, você pode usar o forEach assim:

tarefas.forEach((tarefa, index) => {
    const elementoTarefa = criarElementoTarefa(tarefa, index)

E aí altera tua função pra:

function criarElementoTarefa(tarefa, index) {
    // ...
    botao.onclick = () => {
        console.log('Índice:', index)
        // etc
    }
}

Mas do jeito que tá, já funciona lindamente por causa da referência do objeto.

solução!

Isso tudo tem a ver com passagem de parâmetro por valor ou por referência que o JS faz, deixa eu te explicar:

Quando a gente passa uma variável pra uma função ou pra algum manipulador de evento, como o onclick, o JavaScript pode fazer isso de duas formas: por valor ou por referência. E entender essa diferença é chave pra saber o que tá acontecendo por trás dos panos.

Por valor

Isso acontece com tipos primitivos, tipo:

  • number (número)
  • string (texto)
  • boolean (verdadeiro/falso)
  • null
  • undefined
  • symbol e bigint (mais raros, mas também primitivos)

Quando tu passa um desses pra uma função, o valor é copiado. A função recebe uma cópia do dado, e se ela mudar esse valor dentro da função, não afeta o original.

Tipo assim:

function mudaNumero(x) {
  x = x + 1
  console.log('Dentro da função:', x)
}

let numero = 5
mudaNumero(numero)
console.log('Fora da função:', numero)

Saída:

Dentro da função: 6
Fora da função: 5

Ou seja, o valor foi passado, mas como era primitivo, virou uma cópia e a variável original não foi afetada.

Por referência

Agora, quando a gente tá lidando com objetos, arrays, funções, etc., o que é passado não é uma cópia do conteúdo, e sim uma referência pro mesmo local na memória. Ou seja, se tu mudar algo dentro da função, isso afeta o original.

Exemplo:

function mudaDescricao(obj) {
  obj.descricao = 'Nova descrição'
}

let tarefa = { descricao: 'Estudar JavaScript' }
mudaDescricao(tarefa)
console.log(tarefa.descricao) // 'Nova descrição'

A função recebeu o mesmo objeto que tava fora dela, então qualquer mudança que tu faz dentro dela, se reflete no original. É isso que tá rolando no Fokus :)

Valeu prof. Vini. Agora ficou claro essa passagem de parâmetros...XD