<h2>Memory Management em JavaScript: Garbage Collector e Vazamentos de Memória</h2>
<h3>Como o JavaScript Gerencia Memória</h3>
<p>JavaScript é uma linguagem com gerenciamento automático de memória através do <strong>Garbage Collector (GC)</strong>. Diferentemente de linguagens como C ou C++, você não aloca e libera memória manualmente. O motor JavaScript (V8 no Chrome/Node.js, SpiderMonkey no Firefox) rastreia objetos em uso e remove automaticamente aqueles inacessíveis.</p>
<p>O conceito fundamental é <strong>reachability</strong> (acessibilidade). Um objeto é considerado "vivo" se pode ser alcançado a partir de uma raiz (variáveis globais, funções ativas, referências locais). Quando nenhuma referência aponta para um objeto, ele entra na fila de coleta. Existem dois algoritmos principais: <strong>Reference Counting</strong> (usado raramente hoje) e <strong>Mark and Sweep</strong> (padrão moderno), que marca objetos acessíveis e remove os não marcados.</p>
<pre><code class="language-javascript">// Exemplo: objetos coletáveis
function exemplo() {
let pessoa = { nome: 'João', idade: 30 };
let referencia = pessoa;
pessoa = null; // uma referência removida, mas referencia ainda existe
referencia = null; // agora SEM REFERÊNCIAS - elegível para coleta
}
exemplo();
// Após a função terminar, o objeto é coletado pelo GC</code></pre>
<h3>Vazamentos de Memória: Causas e Detecção</h3>
<p>Um vazamento ocorre quando objetos permanecem na memória sem serem necessários. JavaScript não previne isso automaticamente — é responsabilidade do desenvolvedor. As causas mais comuns são referências globais acidentais, listeners não removidos, closures persistentes e temporizadores esquecidos.</p>
<p>O impacto é real: vazamentos crescentes degradam performance, congelam aplicações e causam crashes em long-running processes (servidores Node.js). Use as DevTools do navegador (aba Memory) para snapshots de heap e identifique padrões de crescimento. No Node.js, ferramentas como <code>clinic.js</code> ou <code>node --inspect</code> oferecem análises detalhadas.</p>
<pre><code class="language-javascript"></code></pre>
<pre><code class="language-javascript"></code></pre>
<h3>Closures, Timers e Armadilhas Comuns</h3>
<p>Closures são poderosos mas perigosos. Eles capturam o escopo da função envolvente permanentemente. Se um closure persiste indefinidamente (exemplo: callback em setInterval), todo objeto referenciado no escopo fica "preso" na memória. Temporizadores esquecidos amplificam o problema exponencialmente.</p>
<p>Outra armadilha clássica: arrays ou objetos crescendo indefinidamente. Caches sem limite também causam vazamentos. A solução é sempre limpar recursos: cancelar timers com <code>clearInterval()</code>, usar WeakMap/WeakSet para referências fracas, implementar limite de tamanho em caches.</p>
<pre><code class="language-javascript"></code></pre>
<pre><code class="language-javascript"></code></pre>
<h3>Práticas de Otimização e Prevenção</h3>
<p>A prevenção começa na arquitetura. Use padrões como <strong>Observer Pattern</strong> com limpeza automática, implemente <strong>lifecycle hooks</strong> (React.useEffect com cleanup, Angular onDestroy), e sempre destaque componentes corretamente. Em Node.js, estruture seus dados para evitar graphs circulares complexas.</p>
<p>Monitore regularmente. Em produção, configure alertas para vazamentos de memória em seus servidores. Use profiling durante desenvolvimento — encontrar problemas cedo é exponencialmente mais barato. Revise code reviews focando em gerenciamento de recursos, especialmente em seções críticas como integrações com APIs externas, WebSockets e long-polling.</p>
<pre><code class="language-javascript"></code></pre>
<pre><code class="language-javascript"></code></pre>
<h2>Conclusão</h2>
<p>Memory management em JavaScript depende de compreender o Garbage Collector e sua mecânica de reachability. <strong>Primeiro ponto</strong>: vazamentos não são inevitáveis — resultam de práticas negligentes (listeners não removidos, timers sem clearance, closures desnecessários). Identificar e corrigir esses padrões previne 95% dos problemas reais.</p>
<p><strong>Segundo ponto</strong>: use ferramentas de profiling (DevTools, clinic.js, inspector) regularmente. Problemas de memória crescem silenciosamente; monitoramento contínuo é a única defesa confiável em produção.</p>
<p><strong>Terceiro ponto</strong>: adote padrões arquiteturais com limpeza explícita (padrão Observer, lifecycle hooks, funções de desinscrição). Código defensivo que antecipa vazamentos é mais profissional e mantível que debugging reativo.</p>
<h2>Referências</h2>
<ol>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management" target="_blank" rel="noopener noreferrer">MDN - Memory Management</a></li>
<li><a href="https://v8.dev/blog/trash-talk" target="_blank" rel="noopener noreferrer">V8 - Garbage Collector Documentation</a></li>
<li><a href="https://nodejs.org/en/docs/guides/diagnosis/" target="_blank" rel="noopener noreferrer">Node.js - Diagnosis Guide (Memory)</a></li>
<li><a href="https://developer.chrome.com/docs/devtools/memory-problems/" target="_blank" rel="noopener noreferrer">Chrome DevTools - Memory Problems</a></li>
<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don't Know JS (Kyle Simpson) - Scope & Closures</a></li>
</ol>