Referência e Valor: Por que você deve saber a diferença
Nos exemplos a seguir são utilizados emojis para nomear variáveis e não devem ser replicados, caso contrário, o seu código retornará um erro de síntaxe.
Se por algum motivo você tentou comparar objetos ou arrays em JavaScript, você provavelmente ficou confuso, porque eles não eram os mesmos apesar de ter um valor/conteúdo idêntico.
Isso acontece porque o JavaScript compara tipos não primitivos com sua referência e não com seu valor real, e não saber disso pode causar dor de cabeça.
Cópia por Valor
Tipos de dados primitivos como String, Number, Boolean, undefined, null, são marcados como tipos Valor, porque, quando copiamos sua informação ou valor para alguma outra variável, essa nova variável copiará seu valor.
Veja o exemplo a seguir.
_8let 🍎 = "Maçã"_8let 💰 = 0_8_8let 🍏 = 🍎 // "Maçã"_8let 👜 = 💰 // 0_8_8console.log(🍏 === 🍎) // true_8console.log(👜 === 💰) // true
Ao comparar as novas variáveis usando console.log(), ele retornará true, pois o JavaScript compara as primitivas de acordo com seu conteúdo.
Cópia por Referência
Por outro lado, os não primitivos, Array, Object e Function, são marcados como tipo de Referência . Porque, quando definimos uma nova variável com suas informações, essa nova variável terá sua referência e não seu valor.
Veja o exemplo a seguir
_6const 🚗 = [💺, 💺, 💺, 💺]_6const 🚓 = [💺, 💺, 💺, 💺]_6const 🚘 = 🚗_6_6console.log(🚓 === 🚗) // false_6console.log(🚘 === 🚗) // true
Vamos voltar a algumas linhas do texto "esta nova variável terá sua referência e não seu valor". Mas, se não terá o valor, como o javascript conseguiu comparar o 🚘 com o 🚗? E por que 🚓 quando comparado a 🚗, JavaScript nos diz que é "diferente"?
A resposta é simples, comparação por referência! Os tipos de dados primitivos são copiados e comparados por valor, e os não primitivos são copiados e comparados por referência.
Ok, mas o que é Referência?
Referências são endereços alocados na memória do seu computador, e quando comparamos duas informações não primitivas, por exemplo, um objeto, o JavaScript compara seu endereço de memória e não seu conteúdo. Vamos ver mais um exemplo.
_13const 👩⚕️ = {_13 nome: "Bia",_13 idade: 28_13};_13_13const 👩🍳 = 👩⚕️;_13_13console.log(👩⚕️.nome); // Bia_13_13👩🍳.nome = "Patricia";_13_13console.log(👩⚕️.nome); // Patricia_13console.log(👩🍳.nome); // Patricia
Quando definimos o nome de 👩🍳 para Patricia, o nome de 👩⚕️ também muda! Isso porque o conteúdo de 👩🍳 é uma referência ao conteúdo de 👩⚕️, portanto, quaisquer alterações em uma cópia de não primitivo, Object, Array, Function o original será afetado.
Por que saber isso é importante?
Se você já usa o React há algum tempo, temos vários hooks e recursos que ajudam no desempenho do nosso programa, e um importante é o array de dependência do useEffect(). Se você colocar um array ou objeto como uma dependência, sua página não funcionará corretamente, e isso é porque useEffect() está comparando não primitivos com sua referência.
Outro exemplo é o useCallback(), usado para memorizar funções e não apenas comparar com sua referência, evitando a criação de outra função idêntica em cada renderização. Caso queira um post falando sobre isso, me deixe saber!
Portanto, saber a diferença entre referência e real valor é fundamental para aprender hooks avançados no React como useEffect(), useCallback() e useMemo().
Lembre-se!
• Os copiados por valor são primitivos.
• Os copiados por referência são os não primitivos.
• Ao comparar não primitivos idênticos, eles retornam false pelo seu tipo de comparação por referência.
• Copiados por valor → String, Number, Boolean, undefined e null.
• Copiados por referência → Array, Object e Function.