Diferenças entre "Valor" e "Referência" em JavaScript
E por que é crucial entender a diferença
JavaScript é uma linguagem orientada a objetos: isso significa que a maioria das coisas em JavaScript são Objetos. Por exemplo, as funções são Objetos. Os únicos elementos que não são objetos são os Dados de Tipos Primitivos: string, number, boolean, null e undefined. Esses tipos de dados primitivos também são imutáveis, o que significa que, uma vez criados, eles não podem ser modificados.
Uma das diferenças entre os dois é que os dados de tipos primitivos são passados como valor e os objetos são passados como referência.
Dados de Tipos Primitivos são passados como valor e Objetos são passados como referência.
O que isso significa? Você pode pensar nisso dessa maneira:
Por Valor: Significa criar uma CÓPIA do original. Imagine gêmeos: eles nascem exatamente iguais, mas o primeiro gêmeo não tem seu cabelo modificado quando o segundo gêmeo corta o próprio.
Por Referência: Significa criar um APELIDO (alias) para o original. Quando sua mãe te chama de "Doce de Leite", embora seu nome seja Eduardo, isso não cria um clone de você mesmo: você ainda é você, mas você pode ser chamado por esses dois nomes muito diferentes.
Vamos ver a forma como os valores primitivos e os objetos se comportam, primeiro quando atribuímos valores com o operador de atribuição (=) e segundo quando passamos para uma função como um parâmetro.
1. Atribuindo um valor com o operador = com Valores Primitivos e Objetos
Com Valores Primitivos, o operador = funciona por valor
Considere o código abaixo:
var name = "Carlos"; var firstName = name; name = "Carla"; console.log(name); // "Carla" console.log(firstName); // "Carlos"
O resultado é bastante direto: é o operador = está trabalhando por valor. O que realmente acontece aqui pode ser simplificado da seguinte forma: Uma variável name
é criada e recebe o valor "Carlos". Um pedaço de memória em JavaScript é alocado para ele. Uma variável firstName
é criada e recebe uma cópia do valor de name
. firstName
tem seu próprio ponto de memória e é independente de name
. Neste momento no código,firstName
também tem um valor "Carlos". Em seguida, alteramos o valor de name
para "Carla". Mas firstName
ainda mantém seu valor original, porque ele vive em um ponto de memória diferente. Ao trabalhar com valores primitivos, o operador = cria uma cópia da variável original. Isso é o que "por valor" significa. Com objetos, o operador = funciona por referência Considere o código abaixo: var myName = { firstName: "Carlos" }; var identity = myName; myName.firstName = "Carla"; console.log(myName.firstName); // "Carla" console.log(identity.firstName); // "Carla"
Aqui, o resultado é o mesmo para as variáveis que contêm objetos. Isso ocorre porque, ao lidar com objetos, o operador = funciona por referência. O que realmente acontece pode ser descrito da seguinte forma: Uma variável myName
é criada e recebe o valor de um objeto que possui uma propriedade chamada firstName
. firstName
tem o valor de "Carlos". É alocado um pedaço em memória no JavaScript para myName
e o objeto que ele contém. Uma variável identity
é criada, apontando uma referência para myName
. Não há espaço em memória dedicado ao valor identity
. Ele apenas aponta para o valor do myName
. Alteramos o valor da propriedade firstName
em myName
para "Carla", ao invés de "Carlos". Quando logamos myName.firstName
, ele exibe o novo valor, que é esperado. Mas quando nós logamos identity.firstName
, ele também exibe o novo valor de myName.firstName
, "Carla". Isso acontece porque identity.firstName
apenas aponta para o lugar em memória de myName.firstName
. Ao trabalhar com objetos, o operador = cria um alias para o objeto original, ele não cria um novo objeto. Isso é o que "por referência" significa. 2. Passando Valores Primitivos e Objetos para uma função Dados de Tipos Primitivos são passados para uma função como valor Se você alterar o valor de um dado de tipo primitivo dentro de uma função, essa alteração não afetará a variável no escopo externo: var myName = "Carlos"; function myNameIs(aName){ aName = "Carla"; } myNameIs(myName); console.log(myName); // "Carlos"
Mesmo que mudando a variávelmyName
dentro da função myNameIs
, quando logamos, depois de chamar a função, ela ainda possui o valor "Carlos". Isso ocorre porque quando os tipos primitivos são passados, eles são passados como valor. Estamos passando uma cópia de myName
: qualquer coisa que você faça para myName
dentro do corpo da função não afetará myName
no escopo global, porque você está passando uma cópia de myName
e não a variável myName
original. Objetos são passados para uma função como referência Quando você está passando algo por referência, você está passando algo que aponta para outra coisa, e não uma cópia do objeto. Portanto, como o JavaScript passa objetos por referência, quando você altera uma propriedade desse objeto dentro da função, a alteração será refletida no escopo externo: var myName = {}; function myNameIs(aName){ aName.firstName = "Carla"; } myNameIs(myName); console.log(myName); // Object {firstName: "Carla"}
Logando a variável myName
depois de ter invocado a função myNameIs
, irá mostrar um objeto com uma chave firstName
com um valor igual a "Carla". O objeto mudou no escopo global quando o passamos para a função. Isso ocorre porque quando você passa um objeto para a função, você não está passando uma cópia. Você está passando algo que aponta para o objeto myName
. Então, quando você altera uma propriedade desse objeto na função, você está mudando a propriedade do objeto no escopo externo. Mas há uma coisa com a qual você deve prestar atenção: var myName = { firstName: "Carla" }; function myNameIs(aName){ aName = { nickName: "Carlita" }; } myNameIs(myName); console.log(myName); // Object {firstName: "Carla"}
Aqui logamos o valor da variável myName
no escopo externo, e verificamos que não foi adicionado uma propriedade nickName
ao objeto. Por quê? Se você olhar com atenção, o que estamos tentando fazer na função é reatribuir o objeto myName
com um novo valor. Você não pode alterar onde myName
aponta, você só pode alterar uma propriedade dentro do objeto myName
, para qualquer outra coisa: var myName = { firstName: "Carla" }; function myNameIs(aName){ aName.nickName = "Carlita"; } myNameIs(myName); console.log(myName); // Object {firstName: "Carla", nickName: "Carlita"}
Créditos Grasp “By Value” and “By Reference” in JavaScript, escrito originalmente por Léna Faure
Create your profile
Only paid subscribers can comment on this post
Check your email
For your security, we need to re-authenticate you.
Click the link we sent to , or click here to sign in.