Imutabilidade, cópia profunda e Map/Set
{ ...objeto } copia só o primeiro nível — um objeto aninhado dentro dele continua sendo a mesma referência nos dois lados.
Você já viu que { ...objeto } resolve o problema de = copiar só a referência. Só que spread tem um limite que costuma surpreender assim que o objeto tem outro objeto dentro dele.
Spread é uma cópia RASA
const usuario = {
nome: "Ana",
endereco: { cidade: "Porto Velho" },
};
const copia = { ...usuario };
copia.nome = "Bia";
usuario.nome; // "Ana" — intacto, o primeiro nível foi copiado de verdade
copia.endereco.cidade = "Manaus";
usuario.endereco.cidade; // "Manaus" — mudou também! endereco é a MESMA referência nos dois objetos{ ...usuario } copia só o primeiro nível de propriedades. Quando uma propriedade é, ela mesma, um objeto ou array, o spread copia a referência pra ela — não o conteúdo. Isso é chamado de cópia rasa (shallow copy), e é a mesma limitação de Object.assign() e de [...array].
structuredClone — cópia profunda de verdade
const copiaProfunda = structuredClone(usuario);
copiaProfunda.endereco.cidade = "Manaus";
usuario.endereco.cidade; // continua "Porto Velho" — copiaProfunda é 100% independentestructuredClone é uma função global (disponível em navegadores modernos e no Node) que copia um objeto recursivamente, nível por nível. Ela não consegue clonar tudo — funções, por exemplo, não sobrevivem ao clone — mas cobre bem a maioria dos casos de dado comum (objetos, arrays, datas, Map, Set).
Map — quando um objeto comum não é suficiente
const contagem = new Map();
contagem.set("maçã", 3);
contagem.set("banana", 5);
contagem.get("maçã"); // 3
contagem.has("uva"); // false
contagem.size; // 2 — não precisa de Object.keys(obj).length
for (const [fruta, qtd] of contagem) {
console.log(fruta, qtd);
}Map faz mais sentido que objeto comum quando a chave não é necessariamente uma string (pode ser um número, um objeto, até uma função), quando você precisa do tamanho direto (.size) ou quando quer ter certeza absoluta da ordem de inserção sem depender de comportamento implícito de objeto.
Set — coleção que garante itens únicos
const idsUnicos = new Set([1, 2, 2, 3, 3, 3]);
idsUnicos.size; // 3 — duplicados somem sozinhos
idsUnicos.has(2); // true
[...idsUnicos]; // [1, 2, 3] — fácil converter de volta pra array normalSet faz mais sentido que array quando o que importa é se um valor existe (e não em que posição), ou quando você precisa remover duplicados sem escrever a lógica de filtro na mão.
Exercício
Dado const idsComDuplicados = [1, 2, 2, 3, 1, 4], produza um array só com os valores únicos, na ordem em que apareceram pela primeira vez.