3 de Janeiro de 2025
Memória sem Mistério
Como entender referência, ciclo de vida, mutação e vazamento sem transformar o assunto em aula de compiladores.
Andrews Ribeiro
Founder & Engineer
4 min Intermediario Frontend
O problema
Memória em JavaScript costuma ser ensinada como um pacote de palavras soltas:
- stack
- heap
- garbage collector
- referência
E muita gente sai disso sabendo repetir os nomes, mas sem conseguir responder o que importa:
- por que esse objeto ainda está vivo?
- por que uma mudança aqui alterou valor em outro lugar?
- por que a RAM desse processo só cresce?
Sem um modelo mental simples, tudo vira “JavaScript sendo estranho”.
Modelo mental
Você não precisa transformar isso em aula de compiladores.
Guarde estas três ideias:
- valores simples costumam ser baratos de copiar
- objetos, arrays e funções costumam circular por referência
- memória só pode ser liberada quando nada mais no programa consegue alcançar aquele valor
Se quiser reduzir ainda mais:
Memória fica muito mais clara quando você pensa em referência, alcance e tempo de vida.
Quebrando o problema
Copiou ou compartilhou?
Esse é o primeiro filtro.
Quando você faz isso:
const a = { name: 'Ana' }
const b = a
você não criou dois objetos.
Criou duas variáveis apontando para o mesmo objeto.
Se esquecer isso, metade dos bugs de mutação já começa.
Quem ainda alcança esse valor?
Um valor não some porque você não olha mais para ele.
Ele some quando o programa inteiro para de conseguir chegar nele.
Por isso objetos continuam vivos quando ainda estão presos em:
- cache
- array global
Map- closure
- listener
Esse valor ainda deveria existir agora?
Essa pergunta é mais útil do que falar do garbage collector como se fosse entidade mística.
O ponto não é “o GC limpou ou não”.
O ponto é:
- esse dado ainda precisava estar aqui?
- esse cache tinha política de limpeza?
- esse listener foi removido?
Vazamento normalmente é acúmulo, não milagre ruim do runtime
Muita gente imagina vazamento como um buraco secreto de memória.
Na prática, o caso mais comum é bem menos glamouroso:
- lista que só cresce
- cache sem expiração
- objeto grande preso em closure
- mapa de sessão sem remoção
Ou seja, o problema costuma estar mais no desenho do ciclo de vida do que no motor da linguagem.
Quando estiver investigando memória ou mutação, faça estas perguntas:
- Esse valor foi mesmo copiado ou duas variáveis apontam para a mesma referência?
- Quem ainda consegue acessar esse objeto no código?
- Esse valor ainda deveria existir agora?
- Existe algum array, cache, closure ou
Mapacumulando dados sem limpeza?
Exemplo simples
Olhe esta armadilha comum:
const user = { name: 'Ana' }
const sameUser = user
sameUser.name = 'Bia'
console.log(user.name)
A saída será:
Bia
Isso não aconteceu por causa de uma “cópia errada”.
user e sameUser apontam para o mesmo objeto na memória. Quando você muda sameUser.name, também está mudando user.name.
Esse detalhe explica boa parte das mutações “misteriosas” que aparecem em:
- estado compartilhado
- apps React
- serviços Node
- código legado cheio de efeito colateral
Erros comuns
- Achar que atribuir objeto a outra variável cria cópia nova.
- Esquecer que referências compartilhadas espalham efeito colateral.
- Acumular dados em caches, stores, arrays ou
Maps sem política de limpeza. - Falar do garbage collector como se ele corrigisse desenho ruim sozinho.
Como um senior pensa
Quem tem mais experiência olha para memória em termos de posse e alcance.
O raciocínio costuma ser:
O problema não é só onde esse dado nasceu. O problema é quem ainda consegue alcançá-lo e por quanto tempo ele fica vivo.
Essa troca de pergunta costuma melhorar muito o debug:
- vazamento deixa de ser abstrato
- mutação deixa de parecer aleatória
- lifecycle começa a ficar visível
O que o entrevistador quer ver
Em entrevista, o que pesa mais é ver se você conecta teoria com bug real.
- você entender a diferença entre cópia de verdade e referência compartilhada
- você conseguir explicar por que um valor “apagado” ainda continua na memória
- você trazer isso para bug real, como mutação silenciosa ou crescimento de RAM
Uma resposta forte costuma ser assim:
Eu penso em memória como ciclo de vida. Se o valor ainda está acessível por algum cache, listener ou closure, ele ainda está vivo, mesmo que eu não queira mais ele ali.
Garbage collector ajuda a limpar o que ficou inalcançável. Ele não conserta arquitetura que continua segurando referência.
Resumo rápido
O que vale manter na cabeça
- Boa parte dos problemas de memória começa com referência compartilhada e ciclo de vida mal pensado, não com o garbage collector falhando.
- Objetos podem continuar vivos mesmo depois de você parar de usar, desde que ainda exista algum caminho para alcançá-los.
- Mutação misteriosa normalmente é só duas variáveis apontando para o mesmo objeto.
- Em entrevista, resposta boa conecta memória a bug real, não a uma aula abstrata sobre heap.
Checklist de pratica
Use isto ao responder
- Consigo explicar a diferença entre copiar valor e compartilhar referência?
- Sei investigar quem ainda alcança um objeto que deveria ter morrido?
- Consigo identificar caches, arrays, listeners e closures que acumulam dados sem limpeza?
- Sei explicar por que garbage collector não corrige desenho ruim sozinho?
Você concluiu este artigo
Próximo passo
Como o event loop funciona Próximo passo →Compartilhar esta página
Copie o link manualmente no campo abaixo.