passar por valor vs passar por referência em JavaScript

se você é novo no JavaScript, é provável que já tenha encontrado algum comportamento engraçado que essa linguagem tem a oferecer (exposição a). No início, essas peculiaridades estranhas podem parecer ridículas e frustrantes, mas prometo que há um método por trás de toda essa loucura.

um dos obstáculos mais difíceis de superar, na minha humilde opinião, é a diferença entre passar por valor e passar por referência. Por que esse conceito é tão complicado? Para começar, você certamente pode chegar muito longe sem realmente entender como o JavaScript interage com valores primitivos e valores de referência. Isso pode, e na maioria das vezes, resultará em uma tonelada de bugs que são difíceis de rastrear e irritantes de corrigir. Em segundo lugar, este é um conceito que surgirá em entrevistas técnicas, então não entender isso contará como uma enorme bandeira vermelha contra você.

não tema, colega leitor! Deixe a educação começar …

tipos de dados primitivos

em JavaScript, podemos dividir os tipos de dados em dois buckets diferentes, tipos de dados primitivos e objetos.

Gráfico ilustrando os tipos de dados primitivos, ou valores, e os tipos de objeto, ou valores de referência

Existem seis tipos de dados primitivos em JavaScript: string, number, boolean, undefined, null, e symbol como de ES6.

os tipos de dados primitivos são passados, ou copiados, por valor e são imutáveis, o que significa que o valor existente não pode ser alterado da maneira que um array ou um objeto pode. Vamos dar uma olhada no código abaixo para ver isso em ação.

Criado usando jsbin.com

Aqui nós criamos duas variáveis, x = 10 e y = x. Como 10 é um número e um valor primitivo, quando definimos y = x estamos realmente copiando o valor, ou seja, 10 e atribuindo-o a y. Também podemos visualizar isso usando o gráfico abaixo.

Se fosse para alterar o valor de x, veremos que y mantém o seu valor de 10. Novamente, isso ocorre porque os valores primitivos são copiados, portanto, o valor de y é independente do valor de x. Pense nisso como fazer uma fotocópia de uma imagem. Depois de fazer a cópia, você tem duas imagens idênticas: um original e um fac-símile. Se você cortasse o original ao meio, apenas o original seria alterado e o fac-símile permaneceria exatamente o mesmo.

Nós substituiu o valor de x, mas y permanece o mesmo

Objetos de Referência

Objetos, por outro lado, são passados por referência e apontar para uma localização na memória para o valor, não o valor em si. Vamos dar uma olhada nisso em nosso código.

as Variáveis x e y agora apontar para objetos, em vez de tipos de dados primitivos

neste exemplo, x é agora um objeto apontando para {dog: "poodle"}. Quando criamos a variável y e atribua a ela o valor de x, agora somos capazes de tocar em várias propriedades de x que inclui o valor para dog, i.e. "poodle". Esta parece exatamente a mesma lógica usada para valores primitivos, mas vamos dar uma olhada em nosso gráfico prático abaixo para ver a diferença sutil, mas importante.

Ambos x e y do ponto a (composto) endereço na memória que armazena uma referência para o objeto

Agora este gráfico parece ser um pouco diferente de quando o nosso variáveis x e y realizada tipos de dados primitivos. Nesta versão, vemos que os valores para x e y não são tipos de dados, mas referências a endereços na memória, o mesmo endereço de fato! Agora vamos dar uma olhada no que acontece para x se adicionar uma nova propriedade de size para y

x ainda retorna um objeto, mas agora ele tem uma propriedade adicional de size também! Novamente, isso ocorre porque x e y apontam para o mesmo objeto de referência, portanto, quaisquer alterações feitas em uma variável serão visíveis na outra.

Gráfico ilustra como uma mudança em y actualiza o valor de referência que é compartilhado com x

Para ajuda-me a lembrar que este conceito, gosto de pensar que os valores de referência como uma casa e as variáveis como pessoas que vivem na casa. Todos os residentes (variáveis) podem dizer “eu tenho uma casa” e apontar para a mesma casa. Se um único residente decide que quer pintar a casa de amarelo, então todos os residentes agora têm uma casa amarela porque é compartilhada.Vamos dar uma olhada em mais um exemplo que contém uma variedade de objetos de referência.

neste código, vamos começar com uma variável person que contém as propriedades de name, age, e hobbies. Quando imprimimos esse objeto no console, obtemos exatamente o que esperamos — o mesmo objeto que acabamos de criar.

em seguida, temos uma função chamada changePerson que recebe um argumento, faz algumas alterações e retorna um objeto. Quando criamos a variável thirdPerson, invocamos a função changePerson passando nosso objeto original de person para ela. O pouco interessante é o que acontece quando imprimimos no console thirdPerson e person novamente.

observe que console.log(thirdPerson) retorna um objeto totalmente novo com novas propriedades. Agora Veja o que console.log(person) retorna. Isso é semelhante ao nosso objeto original, mas contém novos valores de propriedade que foram introduzidos em nossa função changePerson.

verificação de igualdade

finalmente, vamos dar uma olhada em como os tipos de dados primitivos e objetos de referência se comportam com operadores de igualdade.

Quando se trata de tipos de dados primitivos, não importa o que é o direito de a = sinal desde que os valores são os mesmos. Podemos ver isso acima com variáveis a e b que são escritas de forma diferente, mas avaliam o mesmo valor quando usamos o ===, o operador de igualdade estrita.

O oposto é verdadeiro no segundo exemplo para dog e cat. Embora possa parecer que eles contêm valores idênticos, é uma matriz, e um objeto de referência, o que significa que o === é verificar se os dois dog e cat têm a mesma referência para o valor na memória. Por outro lado, bird === dog é verdadeiro porque eles compartilham o mesmo objeto de referência.

o cão e a pássaro compartilhar a mesma referência, enquanto o gato não, apesar de ter uma idêntica matriz

Conclusão

E conclui que a nossa introdução na passagem por valor vs passagem por referência. Há mais tópicos que podem ser abordados sob este guarda-chuva fundamental, incluindo o que acontece quando uma referência é sobrescrita ou perdida, como copiar uma referência para criar um novo objeto e certifique-se de que a cópia é uma cópia profunda, apenas para citar alguns. Eu recomendaria verificar os recursos que usei abaixo, que entram em alguns desses tópicos adicionais com mais detalhes.

Deixe uma resposta

O seu endereço de email não será publicado.