- Tipos Primitivos (Cópia por Valor)
Quando se trabalha com valores primitivos em JavaScript, a atribuição realiza uma cópia do valor.
let primeiroValor = 15;
let segundoValor = primeiroValor; // Cópia por valor
segundoValor = 25;
console.log(primeiroValor); // 15, o original não se altera
console.log(segundoValor); // 25
- Tipos de Objeto (Cópia por Referência)
Para objetos, arrays e outras estruturas complexas, a atribuição copia a referência ao mesmo objeto na memória.
let configuracao = { tema: 'claro' };
let copiaConfig = configuracao; // Cópia por referência
copiaConfig.tema = 'escuro';
console.log(configuracao.tema); // 'escuro', o objeto original é modificado
console.log(configuracao === copiaConfig); // true, apontam para o mesmo objeto
- Exemplos com Desestruturação
Caso 1: Desestruturando uma propriedade primitiva
Ao dseestruturar uma propriedade primitiva, o valor é copiado independentemente.
let pessoa = { nome: 'Carlos', idade: 30 };
let { nome } = pessoa; // Equivalente a let nome = pessoa.nome;
nome = 'André';
console.log(nome); // 'André'
console.log(pessoa.nome); // 'Carlos', o objeto original não é afetado
// Pois 'nome' é uma string (tipo primitivo), cópia por valor
Caso 2: Desestruturando uma propriedade objeto
Propriedades que são objetos mantêm a referência após a desestruturação.
let usuario = {
nome: 'Carlos',
localizacao: { cidade: 'São Paulo' },
interesses: ['leitura', 'cinema']
};
let { localizacao } = usuario; // 'localizacao' é objeto, cópia por referência
localizacao.cidade = 'Rio de Janeiro';
console.log(usuario.localizacao.cidade); // 'Rio de Janeiro', o original é alterado
let { interesses } = usuario; // 'interesses' é array (tipo objeto), cópia por referência
interesses.push('esportes');
console.log(usuario.interesses); // ['leitura', 'cinema', 'esportes'], modificado
Caso 3: Desestruturação aninhada
Em desestruturação aninhada, as referências são preservadas em todos os níveis de objeetos.
let dados = {
informacao: {
pessoal: {
nome: 'Carlos',
idade: 30
}
}
};
let { informacao: { pessoal } } = dados;
pessoal.idade = 35;
console.log(dados.informacao.pessoal.idade); // 35, o original é modificado
// Pois 'pessoal' é um objeto, mantém a referência
- Atribuição Direta versus Desestruturação
A cópia por valor ocorre tanto para atribuição direta de propriedades primitivas quento para desestruturação delas.
// Atribuição direta
let objetoA = { nome: 'Carlos' };
let valorDireto = objetoA.nome; // Primitivo, cópia por valor
valorDireto = 'André';
console.log(objetoA.nome); // 'Carlos', sem alteração
// Desestruturação
let { nome: aliasNome } = objetoA; // Primitivo, cópia por valor
aliasNome = 'Fernando';
console.log(objetoA.nome); // 'Carlos', sem alteração
// Porém, ao desestruturar uma propriedade objeto
let objetoB = { info: { nome: 'Carlos' } };
let { info: copiaInfo } = objetoB; // Objeto, cópia por referência
copiaInfo.nome = 'Ricardo';
console.log(objetoB.info.nome); // 'Ricardo', alterado!
- Como Evitar Modificações Acidentais
Método 1: Cópia Profunda
Utilize técnicas de cópia profunda para criar uma instância totalmente nova do objeto.
let original = {
nome: 'Carlos',
localizacao: { cidade: 'São Paulo' }
};
// Cópia profunda usando JSON (com limitações para funções, etc.)
let copiaProfunda = JSON.parse(JSON.stringify(original));
// Ou usando a API moderna structuredClone
let copiaModerna = structuredClone(original);
let { localizacao } = copiaModerna;
localizacao.cidade = 'Belo Horizonte';
console.log(original.localizacao.cidade); // 'São Paulo', original intacto
Método 2: Desestruturação Seletiva
Desestruture apenas os valores primitivos necessários para evitar referências indesejadas.
let endereco = {
localizacao: {
cidade: 'São Paulo',
detalhes: { rua: 'Rua Principal' }
}
};
// Desestruture apenas as chaves primitivas
let { localizacao: { cidade, detalhes: { rua } } } = endereco;
// Agora 'cidade' e 'rua' são strings (primitivos), cópia por valor
// Modificações nelas não afetam o objeto original
Resumo das Regras
- Tipos Primitivos (string, number, boolean, null, undefined, symbol, bigint):
- Atribuição é cópia por valor.
- Desestruturação também é cópia por valor.
- Tipos de Objeto (objetos, arrays, funções, Date, etc.):
- Atribuição é cópia por referência.
- Na desestruturação, se a propriedade for um tipo objeto, mantém a cópia por referência.
- Comportamento de Modificação:
- Para variáveis primitivas, a reatribuição não afeta a fonte.
- Para variáveis objeto, modificar propriedades do objeto afeta a fonte, mas reatribuir a variável não afeta.
// Exemplo de reatribuição vs modificação de propriedade
let objOriginal = { cor: 'vermelho' };
let objCopia = objOriginal;
objCopia.cor = 'azul'; // Modifica propriedade, objOriginal também muda
console.log(objOriginal.cor); // 'azul'
objCopia = { cor: 'verde' }; // Reatribui a variável, objOriginal não muda
console.log(objOriginal.cor); // 'azul'