<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Henrique Alves Rosa</title>
    <description>The latest articles on DEV Community by Lucas Henrique Alves Rosa (@lucasharosa).</description>
    <link>https://dev.to/lucasharosa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4172290%2F5edd0723-b56d-467f-ab61-d98b12ad81bc.png</url>
      <title>DEV Community: Lucas Henrique Alves Rosa</title>
      <link>https://dev.to/lucasharosa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasharosa"/>
    <language>en</language>
    <item>
      <title>Garbage Collector: quem limpa a memória do JavaScript?</title>
      <dc:creator>Lucas Henrique Alves Rosa</dc:creator>
      <pubDate>Mon, 26 Oct 2026 16:46:24 +0000</pubDate>
      <link>https://dev.to/lucasharosa/garbage-collector-quem-limpa-a-memoria-do-javascript-2bg1</link>
      <guid>https://dev.to/lucasharosa/garbage-collector-quem-limpa-a-memoria-do-javascript-2bg1</guid>
      <description>&lt;p&gt;Se JavaScript possui Garbage Collector, por que ainda existe &lt;em&gt;memory leak&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;A dúvida faz sentido. Se o ambiente gerencia a memória automaticamente, parece razoável esperar que ele também descarte tudo aquilo de que nossa aplicação não precisa mais.&lt;/p&gt;

&lt;p&gt;Mas existe uma diferença entre &lt;strong&gt;um objeto que não pode mais ser alcançado&lt;/strong&gt; e &lt;strong&gt;um objeto que deixou de ser útil&lt;/strong&gt;. O Garbage Collector trabalha com a primeira ideia. A segunda depende das decisões da aplicação.&lt;/p&gt;

&lt;p&gt;Este é mais um artigo da série &lt;strong&gt;“Coisas que usamos todos os dias, mas raramente paramos para entender.”&lt;/strong&gt; No texto sobre stack, heap e memória, explorei como os dados são armazenados e compartilhados. Agora, vamos aprofundar o que acontece quando esses dados poderiam deixar de existir, mas alguma referência continua mantendo-os acessíveis.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A memória não desaparece porque sua administração é automática
&lt;/h2&gt;

&lt;p&gt;Quando criamos objetos, arrays e funções, o motor precisa de memória para representá-los. O heap é uma região administrada pelo motor para armazenar objetos e outras estruturas.&lt;/p&gt;

&lt;p&gt;Não precisamos chamar &lt;code&gt;malloc&lt;/code&gt; e &lt;code&gt;free&lt;/code&gt;, como fazemos em determinadas situações em C. O ambiente acompanha as alocações e executa a coleta de lixo.&lt;/p&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;criarResumo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Relatório de vendas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;criarResumo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função retorna uma string, sem expor o objeto &lt;code&gt;report&lt;/code&gt;. Se nenhuma outra referência mantiver aquele objeto alcançável, sua memória poderá ser recuperada.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Poderá&lt;/strong&gt; é importante: não controlamos o instante exato da coleta. Também não há garantia de devolução imediata dessa memória ao sistema operacional.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Referências: os caminhos até os objetos
&lt;/h2&gt;

&lt;p&gt;Uma atribuição de objeto não cria automaticamente uma cópia independente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Relatório mensal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "Relatório mensal"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A variável &lt;code&gt;report&lt;/code&gt; deixou de permitir acesso ao objeto. O array &lt;code&gt;history&lt;/code&gt;, porém, continua permitindo esse acesso.&lt;/p&gt;

&lt;p&gt;Atribuir &lt;code&gt;null&lt;/code&gt; removeu um caminho, mas não todos.&lt;/p&gt;

&lt;p&gt;Esse exemplo ajuda a entender por que espalhar atribuições de &lt;code&gt;null&lt;/code&gt; pelo código não resolve automaticamente problemas de memória. Precisamos identificar &lt;strong&gt;quem ainda mantém a referência&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Reachability: o que ainda pode ser alcançado?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Reachability&lt;/em&gt;, ou alcançabilidade, descreve a possibilidade de chegar a um objeto seguindo referências a partir de um conjunto de raízes considerado pelo motor.&lt;/p&gt;

&lt;p&gt;Essas raízes incluem referências associadas à execução ativa e ao ambiente. A partir delas, o coletor percorre os objetos acessíveis e suas relações.&lt;/p&gt;

&lt;p&gt;No exemplo anterior, enquanto &lt;code&gt;history&lt;/code&gt; permanecer alcançável, seu conteúdo também permanece.&lt;/p&gt;

&lt;p&gt;Por outro lado, referências circulares não impedem necessariamente a coleta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;criarCiclo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;criarCiclo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os objetos referenciam um ao outro, mas nenhum é retornado ou guardado fora da função. Se o conjunto se tornar inalcançável, um coletor baseado em rastreamento consegue identificá-lo como coletável.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ter uma referência recebida de outro objeto não é suficiente para continuar vivo: importa de onde parte o caminho até ele.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Mark-and-sweep: um modelo para entender a coleta
&lt;/h2&gt;

&lt;p&gt;O algoritmo &lt;strong&gt;mark-and-sweep&lt;/strong&gt; ajuda a visualizar esse processo em duas etapas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Marcação:&lt;/strong&gt; partir das raízes e marcar os objetos alcançáveis, percorrendo suas referências.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Varredura:&lt;/strong&gt; identificar o armazenamento dos objetos não marcados e torná-lo disponível para reutilização.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Esse modelo explica por que um ciclo isolado pode ser coletado: nenhum caminho a partir das raízes chega aos objetos do ciclo.&lt;/p&gt;

&lt;p&gt;Implementações reais vão além desse desenho. O V8, por exemplo, utiliza técnicas geracionais, marcação e compactação, além de trabalho incremental, paralelo e concorrente. Essas técnicas distribuem trabalho e reduzem determinados impactos, mas não eliminam todo o custo nem todas as pausas.&lt;/p&gt;

&lt;p&gt;Não precisamos dominar cada detalhe do coletor para investigar um vazamento. O primeiro passo costuma ser localizar o caminho que mantém os dados vivos.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Um exemplo: fechamos a tela, mas guardamos os dados
&lt;/h2&gt;

&lt;p&gt;Imagine uma aplicação que mantém o estado de telas abertas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;screenStates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;openScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Registro &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;screenStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;closeScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Tela &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; fechada`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao abrir uma tela, criamos seus dados e os guardamos no Map. Ao fechar, apenas registramos uma mensagem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;openScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`screen-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;closeScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`screen-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screenStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As telas foram fechadas para a aplicação, mas os dez estados continuam armazenados. Enquanto o Map permanecer acessível, existe um caminho até todos esses registros.&lt;/p&gt;

&lt;p&gt;O GC não tem como concluir que a mensagem “tela fechada” significa que os dados podem ser descartados.&lt;/p&gt;

&lt;p&gt;Se o estado não precisa ser preservado, a função de encerramento deve remover a entrada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;closeScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;screenStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso remove a referência mantida pelo Map. Se outro lugar ainda guardar o mesmo estado, ele continuará alcançável por esse outro caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Closures: a função terminou, mas o acesso continua
&lt;/h2&gt;

&lt;p&gt;Closures permitem que uma função mantenha acesso ao ambiente léxico em que foi criada, mesmo depois de a chamada externa terminar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exporters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;exporters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada função adicionada a &lt;code&gt;exporters&lt;/code&gt; permite acessar um relatório:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerExporter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;report-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A chamada terminou, mas o array mantém a função, e a função mantém acesso ao relatório.&lt;/p&gt;

&lt;p&gt;Esse comportamento pode ser exatamente o que queremos: permitir exportar o relatório depois. O problema aparece quando a opção de exportação deixa de existir, mas o callback continua registrado.&lt;/p&gt;

&lt;p&gt;Uma solução é definir explicitamente o encerramento desse registro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exporters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;registerExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;exporters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unregisterExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;exporters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Closures não são vazamentos por natureza. Precisamos alinhar a duração dos callbacks à duração da funcionalidade que eles atendem.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Event listeners: remover o elemento pode não bastar
&lt;/h2&gt;

&lt;p&gt;Considere uma tela que registra um listener no &lt;code&gt;window&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mountPanel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Painel de resultados&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;viewportWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao desmontar, removemos o painel do documento, mas mantemos o listener. Durante a vida daquela página, o &lt;code&gt;window&lt;/code&gt; continua acessível e mantém o callback, que acessa &lt;code&gt;panel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O elemento saiu da árvore visual, mas ainda pode ser alcançado.&lt;/p&gt;

&lt;p&gt;A limpeza deve acompanhar os recursos registrados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para remover o listener, precisamos usar a mesma função e uma configuração compatível de &lt;code&gt;capture&lt;/code&gt;. Criar outra função com o mesmo corpo não remove a anterior.&lt;/p&gt;

&lt;p&gt;Também não devemos concluir que todo elemento removido com listener causa vazamento. Se o elemento, o listener e os objetos relacionados se tornarem inalcançáveis, o conjunto pode ser coletado. Neste exemplo, o caminho persistente passa pelo &lt;code&gt;window&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Timers também mantêm trabalho registrado
&lt;/h2&gt;

&lt;p&gt;Um intervalo pode continuar usando dados de uma tela que já foi encerrada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startMonitoring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Quantidade de linhas:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stopMonitoring&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enquanto o intervalo estiver ativo, o ambiente mantém o callback registrado. Como ele acessa &lt;code&gt;report&lt;/code&gt;, esse registro pode prolongar a vida do relatório.&lt;/p&gt;

&lt;p&gt;O código que inicia o monitoramento também precisa encerrar esse trabalho:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stopMonitoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;startMonitoring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Quando o monitoramento deixar de ser necessário:&lt;/span&gt;
&lt;span class="nf"&gt;stopMonitoring&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um &lt;code&gt;setTimeout&lt;/code&gt; distante também pode reter dados enquanto aguarda execução. Isso pode ser legítimo; a questão é cancelar o agendamento quando sua finalidade deixar de existir.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Caches: guardar mais dados também exige uma política
&lt;/h2&gt;

&lt;p&gt;Um cache simples pode crescer indefinidamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reportsCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cacheReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;reportsCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se chegam novos IDs continuamente e nenhuma entrada é removida, o consumo pode continuar aumentando.&lt;/p&gt;

&lt;p&gt;Para a aplicação, talvez relatórios antigos já não tenham utilidade. Para o GC, eles continuam acessíveis pelo Map.&lt;/p&gt;

&lt;p&gt;Uma política de cache pode considerar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limite de entradas ou de memória.&lt;/li&gt;
&lt;li&gt;Expiração com remoção efetiva.&lt;/li&gt;
&lt;li&gt;Descarte dos itens menos utilizados.&lt;/li&gt;
&lt;li&gt;Invalidação quando os dados mudam.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Registrar uma data de expiração sem remover as entradas não elimina as referências. Mesmo uma expiração verificada apenas na leitura pode deixar entradas nunca mais consultadas ocupando espaço.&lt;/p&gt;

&lt;p&gt;O comportamento de descarte precisa fazer parte do desenho do cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Memória crescendo sempre significa vazamento?
&lt;/h2&gt;

&lt;p&gt;Não. A aplicação pode estar carregando mais dados, preenchendo um cache legítimo ou criando objetos temporários que ainda serão coletados.&lt;/p&gt;

&lt;p&gt;É comum observar crescimento seguido de quedas. Também existe diferença entre memória do heap JavaScript e consumo total do processo, que inclui outras estruturas e recursos.&lt;/p&gt;

&lt;p&gt;Uma suspeita mais forte aparece quando repetimos uma operação que deveria retornar a um estado equivalente, mas cada repetição mantém mais objetos desnecessários.&lt;/p&gt;

&lt;p&gt;Por exemplo: abrir e fechar o mesmo painel várias vezes deveria permitir descartar os estados anteriores, caso o produto não precise preservá-los.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Como investigar no DevTools?
&lt;/h2&gt;

&lt;p&gt;Uma abordagem prática é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abrir a aplicação e concluir seu carregamento inicial.&lt;/li&gt;
&lt;li&gt;Capturar um heap snapshot.&lt;/li&gt;
&lt;li&gt;Repetir algumas vezes o fluxo suspeito.&lt;/li&gt;
&lt;li&gt;Voltar ao mesmo estado funcional.&lt;/li&gt;
&lt;li&gt;Capturar outro snapshot e comparar os objetos retidos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O painel &lt;strong&gt;Retainers&lt;/strong&gt; ajuda a localizar o caminho que mantém um objeto acessível. Já o tamanho retido ajuda a perceber que um objeto pequeno pode sustentar uma estrutura muito maior.&lt;/p&gt;

&lt;p&gt;Um callback, por exemplo, pode ocupar pouco espaço e ainda manter um relatório inteiro.&lt;/p&gt;

&lt;p&gt;A coleta forçada disponível nas ferramentas pode auxiliar o diagnóstico, mas não deve fazer parte da lógica da aplicação. Também é importante evitar guardar objetos no console durante a investigação, porque as próprias ferramentas podem mantê-los acessíveis.&lt;/p&gt;

&lt;p&gt;Depois de encontrar o caminho de retenção, conseguimos avaliar se ele é necessário ou se faltou uma etapa de limpeza.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. O que continua sendo responsabilidade da aplicação?
&lt;/h2&gt;

&lt;p&gt;Não precisamos sair atribuindo &lt;code&gt;null&lt;/code&gt; a todas as variáveis locais. Precisamos definir o tempo de vida das estruturas e dos registros que mantemos.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ação&lt;/th&gt;
&lt;th&gt;Encerramento a considerar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Adicionar estado a uma coleção persistente&lt;/td&gt;
&lt;td&gt;Remover quando não precisar preservá-lo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registrar um listener&lt;/td&gt;
&lt;td&gt;Desregistrar quando sua finalidade terminar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iniciar um intervalo&lt;/td&gt;
&lt;td&gt;Cancelar ao encerrar o monitoramento&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guardar um callback&lt;/td&gt;
&lt;td&gt;Remover quando a operação deixar de existir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Armazenar dados em cache&lt;/td&gt;
&lt;td&gt;Aplicar uma política de descarte&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Essas ações não liberam necessariamente a memória naquele instante. Elas removem caminhos de acesso que poderiam impedir a coleta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O gerenciamento automático de memória retira uma responsabilidade importante das nossas mãos, mas a aplicação continua definindo o que permanece acessível.&lt;/p&gt;

&lt;p&gt;Um Map pode guardar estados de telas fechadas. Um listener pode manter um elemento fora do documento. Um timer pode preservar um relatório. Uma closure pode prolongar o acesso a dados depois que a função externa terminou.&lt;/p&gt;

&lt;p&gt;Em todos esses casos, o coletor pode estar funcionando corretamente. O problema é que o programa continua mantendo referências para informações de que já não precisa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O GC sabe o que não pode mais ser alcançado; ele não sabe o que deixou de ser útil para sua aplicação.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Entender essa diferença muda a investigação: em vez de perguntar apenas “por que o JavaScript não limpou?”, passamos a procurar “quem ainda está mantendo isso vivo?”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Memory_management" rel="noopener noreferrer"&gt;MDN — Memory management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v8.dev/blog/trash-talk" rel="noopener noreferrer"&gt;V8 — Trash talk: the Orinoco garbage collector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures" rel="noopener noreferrer"&gt;MDN — Closures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener" rel="noopener noreferrer"&gt;MDN — removeEventListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/devtools/memory-problems" rel="noopener noreferrer"&gt;Chrome DevTools — Fix memory problems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>RAG: como conectar uma LLM aos dados da sua aplicação, e quando isso faz sentido</title>
      <dc:creator>Lucas Henrique Alves Rosa</dc:creator>
      <pubDate>Wed, 21 Oct 2026 20:44:07 +0000</pubDate>
      <link>https://dev.to/lucasharosa/rag-como-conectar-uma-llm-aos-dados-da-sua-aplicacao-e-quando-isso-faz-sentido-33af</link>
      <guid>https://dev.to/lucasharosa/rag-como-conectar-uma-llm-aos-dados-da-sua-aplicacao-e-quando-isso-faz-sentido-33af</guid>
      <description>&lt;p&gt;Imagine um assistente que precisa responder a uma pergunta sobre as regras da sua empresa. O modelo consegue escrever uma resposta convincente, mas de onde virão as informações sobre aquele regulamento interno?&lt;/p&gt;

&lt;p&gt;Você poderia enviar todos os documentos junto com cada pergunta. Isso pode funcionar para um conjunto pequeno, mas fica mais difícil conforme aumentam o volume, a diversidade e a frequência de atualização das informações.&lt;/p&gt;

&lt;p&gt;Uma alternativa é procurar primeiro o conteúdo necessário e fornecer esse material ao modelo. Essa é a ideia central de RAG.&lt;/p&gt;

&lt;p&gt;Este artigo faz parte da série &lt;strong&gt;“IA aplicada ao desenvolvimento de software”&lt;/strong&gt; Vamos explorar o que significa Retrieval-Augmented Generation, como suas etapas funcionam e quais decisões aparecem ao aplicar essa arquitetura. No final, vou conectar os conceitos à análise de uma aplicação educacional minha.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. O que é RAG?
&lt;/h2&gt;

&lt;p&gt;RAG significa &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;, ou geração aumentada por recuperação. É uma abordagem que combina a recuperação de informações em fontes externas com a geração de uma resposta por um modelo de linguagem.&lt;/p&gt;

&lt;p&gt;Em vez de depender apenas do conhecimento aprendido durante o treinamento, o modelo recebe conteúdo recuperado para aquela solicitação.&lt;/p&gt;

&lt;p&gt;Pense em uma pergunta como:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Qual é o procedimento para solicitar reembolso de uma viagem?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A aplicação pode buscar a política de viagens, selecionar os trechos sobre despesas reembolsáveis e prazos e enviá-los à LLM junto com a pergunta. O modelo usa esse contexto para elaborar a resposta.&lt;/p&gt;

&lt;p&gt;Os documentos não são automaticamente incorporados aos parâmetros do modelo. Nesse fluxo, eles são disponibilizados durante a geração, sem exigir um novo treinamento a cada atualização da política.&lt;/p&gt;

&lt;p&gt;O trabalho de Lewis e colaboradores, publicado em 2020, apresentou uma arquitetura que combina recuperação e geração para tarefas intensivas em conhecimento. Desde então, o termo também passou a ser usado para diferentes sistemas que seguem esse princípio.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Qual problema essa abordagem ajuda a resolver?
&lt;/h2&gt;

&lt;p&gt;Uma LLM não conhece automaticamente os dados privados e atuais da sua aplicação. Mesmo quando consegue acessar ferramentas, alguém precisa definir como essas ferramentas consultam as fontes e quais resultados chegam ao modelo.&lt;/p&gt;

&lt;p&gt;Isso importa quando a resposta depende de informações como contratos, manuais internos, documentação de produtos ou procedimentos que mudam com frequência.&lt;/p&gt;

&lt;p&gt;RAG oferece um caminho para selecionar conteúdo dessas fontes e disponibilizá-lo como evidência. Também permite associar a resposta aos documentos utilizados, desde que a aplicação preserve essa relação.&lt;/p&gt;

&lt;p&gt;Mas ele não garante que a informação recuperada seja correta nem que o modelo a interprete adequadamente. A qualidade continua dependendo das fontes, da recuperação e da geração.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Como o processo funciona?
&lt;/h2&gt;

&lt;p&gt;Uma implementação comum tem dois momentos: a preparação das fontes e o atendimento de uma solicitação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparação das fontes
&lt;/h3&gt;

&lt;p&gt;A aplicação extrai o conteúdo dos documentos, organiza os metadados e cria uma estrutura que permita pesquisar esse material.&lt;/p&gt;

&lt;p&gt;Dependendo da abordagem, isso pode envolver:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extrair texto de PDFs, páginas ou outros arquivos.&lt;/li&gt;
&lt;li&gt;Dividir documentos em trechos.&lt;/li&gt;
&lt;li&gt;Associar origem, versão, seção e permissões a cada trecho.&lt;/li&gt;
&lt;li&gt;Criar índices textuais, representações vetoriais ou ambos.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Atendimento da solicitação
&lt;/h3&gt;

&lt;p&gt;Quando chega uma pergunta, a aplicação:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identifica o usuário e seu contexto de acesso.&lt;/li&gt;
&lt;li&gt;Busca informações nas fontes autorizadas.&lt;/li&gt;
&lt;li&gt;Seleciona os resultados pertinentes.&lt;/li&gt;
&lt;li&gt;Monta o contexto enviado à LLM.&lt;/li&gt;
&lt;li&gt;Gera e valida a resposta.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essa divisão ajuda a perceber que RAG vai além de “colocar documentos no prompt”. Existe uma etapa de recuperação que precisa encontrar o material adequado para cada solicitação.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Por que dividir documentos em trechos?
&lt;/h2&gt;

&lt;p&gt;Um manual pode ter centenas de páginas, mas a pergunta talvez dependa de apenas uma seção. Dividir o conteúdo em partes menores, os chamados &lt;em&gt;chunks&lt;/em&gt;, permite recuperar porções específicas.&lt;/p&gt;

&lt;p&gt;A dificuldade é preservar significado.&lt;/p&gt;

&lt;p&gt;Um trecho pequeno demais pode separar uma regra de suas condições. Um trecho grande demais pode trazer várias informações sem relação com a pergunta.&lt;/p&gt;

&lt;p&gt;Imagine uma política com esta estrutura:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Despesas de hospedagem são reembolsáveis, desde que respeitem os limites e as condições definidos na seção seguinte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se a recuperação encontra apenas a primeira parte, o modelo pode receber uma regra incompleta.&lt;/p&gt;

&lt;p&gt;Por isso, o tamanho do trecho não deve ser a única preocupação. Títulos, seções, tabelas, referências e continuidade entre parágrafos também importam. Em determinados casos, faz sentido buscar um trecho e incluir a seção maior à qual ele pertence.&lt;/p&gt;

&lt;p&gt;Não existe um tamanho universal que funcione igualmente bem para contratos, perguntas frequentes e documentação técnica.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. O que são embeddings?
&lt;/h2&gt;

&lt;p&gt;Embeddings são representações numéricas de informações, como textos. Eles podem ser usados para comparar proximidade entre uma pergunta e os trechos disponíveis.&lt;/p&gt;

&lt;p&gt;Considere:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como recuperar o acesso à minha conta?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Um documento pode usar a expressão “redefinição de senha”, sem repetir exatamente as palavras da pergunta. Uma busca baseada em embeddings pode ajudar a encontrar essa relação semântica.&lt;/p&gt;

&lt;p&gt;Normalmente, a aplicação calcula embeddings dos trechos durante a preparação e calcula uma representação da consulta durante a busca. Depois, compara essas representações para selecionar candidatos.&lt;/p&gt;

&lt;p&gt;Ainda assim, proximidade semântica não significa que um trecho seja verdadeiro, atual, autorizado ou suficiente para responder. Essas condições precisam de tratamento próprio.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Preciso de um banco vetorial para usar RAG?
&lt;/h2&gt;

&lt;p&gt;Não necessariamente. A recuperação pode usar diferentes mecanismos.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Método&lt;/th&gt;
&lt;th&gt;Como procura&lt;/th&gt;
&lt;th&gt;Onde pode ajudar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Busca textual&lt;/td&gt;
&lt;td&gt;Termos e correspondências no texto&lt;/td&gt;
&lt;td&gt;Códigos, nomes e expressões específicas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Busca vetorial&lt;/td&gt;
&lt;td&gt;Proximidade entre representações&lt;/td&gt;
&lt;td&gt;Perguntas e documentos com vocabulários diferentes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Busca híbrida&lt;/td&gt;
&lt;td&gt;Combinação de busca textual e vetorial&lt;/td&gt;
&lt;td&gt;Acervos com necessidades variadas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consultas estruturadas&lt;/td&gt;
&lt;td&gt;Campos, relações e filtros explícitos&lt;/td&gt;
&lt;td&gt;Registros identificados por aluno, cliente, período ou produto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O importante é entender o problema de recuperação. Se a solicitação contém um número de contrato, uma consulta exata pode ser mais apropriada do que procurar contratos semanticamente semelhantes.&lt;/p&gt;

&lt;p&gt;Também podemos combinar abordagens: obter os dados de um cliente por chave e recuperar trechos de um manual relacionados à sua dúvida.&lt;/p&gt;

&lt;p&gt;Um banco com suporte a vetores pode fazer parte da solução, mas sua adoção não substitui essa análise.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. O que é reranking?
&lt;/h2&gt;

&lt;p&gt;Uma busca inicial pode encontrar vários trechos potencialmente relevantes. O &lt;em&gt;reranking&lt;/em&gt; é uma etapa adicional que reordena esses candidatos de acordo com sua relação com a solicitação.&lt;/p&gt;

&lt;p&gt;Por exemplo, a busca pode retornar vinte trechos sobre viagens corporativas. Uma etapa posterior compara os candidatos com a pergunta específica e prioriza aqueles que tratam de reembolso de hospedagem.&lt;/p&gt;

&lt;p&gt;Isso pode melhorar a seleção, mas acrescenta custo, latência e outro componente para avaliar.&lt;/p&gt;

&lt;p&gt;A quantidade de trechos recuperados também exige cuidado. Enviar mais candidatos pode aumentar a chance de incluir a evidência necessária, mas também pode acrescentar conteúdo redundante ou contraditório.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Contexto maior não garante resposta melhor
&lt;/h2&gt;

&lt;p&gt;O modelo ter espaço para receber muitos tokens não significa que todos eles contribuirão para a resposta.&lt;/p&gt;

&lt;p&gt;O estudo &lt;em&gt;Lost in the Middle&lt;/em&gt; mostrou, nos modelos e nas tarefas avaliadas, que a posição da informação relevante dentro de contextos longos podia afetar o desempenho. Isso não determina o comportamento de toda aplicação ou modelo, mas reforça a necessidade de avaliar como o contexto é utilizado.&lt;/p&gt;

&lt;p&gt;Por outro lado, cortar informações também pode prejudicar a resposta. Uma exceção antiga, uma observação complementar ou uma condição específica pode mudar a interpretação.&lt;/p&gt;

&lt;p&gt;O objetivo é fornecer contexto suficiente, relevante e organizado. Reduzir o tamanho do prompt é uma possibilidade de otimização, não uma prova de qualidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. RAG elimina alucinações?
&lt;/h2&gt;

&lt;p&gt;Não. Ele pode fornecer evidências que ajudam a fundamentar a resposta, mas ainda existem diferentes formas de falhar.&lt;/p&gt;

&lt;p&gt;A recuperação pode selecionar um documento antigo, deixar de encontrar a seção correta ou retornar apenas parte de uma regra. Mesmo com bons trechos, o modelo pode interpretar mal o conteúdo ou apresentar uma conclusão que não está sustentada pelas fontes.&lt;/p&gt;

&lt;p&gt;Por isso, é importante definir o comportamento quando faltam evidências. Em alguns produtos, a resposta adequada é informar que não foi possível confirmar a informação, em vez de completar a lacuna.&lt;/p&gt;

&lt;p&gt;Referências também precisam ser verificadas. Uma resposta citar um documento existente não significa que aquele documento sustente a afirmação feita.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Atualização e controle de acesso fazem parte da arquitetura
&lt;/h2&gt;

&lt;p&gt;Se um documento muda, a representação usada na recuperação precisa acompanhar essa mudança. Isso pode exigir atualizar índices, recalcular embeddings e remover versões substituídas.&lt;/p&gt;

&lt;p&gt;Também precisamos preservar as permissões. Em uma aplicação com várias instituições, o usuário só deve recuperar conteúdo que está autorizado a acessar.&lt;/p&gt;

&lt;p&gt;Não basta recuperar informações de todas as instituições e pedir ao modelo que ignore as demais. A restrição deve acontecer antes de o conteúdo ser disponibilizado à geração.&lt;/p&gt;

&lt;p&gt;Outro cuidado é tratar os documentos recuperados como dados, e não como instruções confiáveis. Um texto encontrado pode conter comandos que tentem alterar o comportamento do assistente. A arquitetura precisa considerar esse risco ao montar o contexto e disponibilizar ferramentas.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Como avaliar uma solução com RAG?
&lt;/h2&gt;

&lt;p&gt;É útil separar duas avaliações.&lt;/p&gt;

&lt;p&gt;A primeira pergunta é: &lt;strong&gt;a recuperação encontrou as evidências necessárias?&lt;/strong&gt; Para responder, precisamos de casos em que sabemos quais documentos ou trechos deveriam estar disponíveis.&lt;/p&gt;

&lt;p&gt;A segunda é: &lt;strong&gt;o modelo produziu uma resposta adequada a partir dessas evidências?&lt;/strong&gt; Aqui entram fidelidade, completude, clareza e utilidade.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimensão&lt;/th&gt;
&lt;th&gt;Pergunta de avaliação&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Recuperação&lt;/td&gt;
&lt;td&gt;As evidências necessárias foram encontradas?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relevância&lt;/td&gt;
&lt;td&gt;Os resultados ajudam a responder à solicitação?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fidelidade&lt;/td&gt;
&lt;td&gt;As afirmações estão sustentadas pelas fontes?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Completude&lt;/td&gt;
&lt;td&gt;Alguma condição ou exceção importante ficou de fora?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Atualidade&lt;/td&gt;
&lt;td&gt;A resposta utiliza a versão correta da informação?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acesso&lt;/td&gt;
&lt;td&gt;Apenas fontes autorizadas foram disponibilizadas?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desempenho&lt;/td&gt;
&lt;td&gt;Qual é o custo e a latência do fluxo completo?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Uma resposta bem escrita pode esconder uma recuperação incompleta. Avaliar apenas a aparência do texto final deixa parte importante do sistema sem verificação.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Um caso real: minha aplicação educacional
&lt;/h2&gt;

&lt;p&gt;Na minha aplicação, a LLM gera um Relatório Geral, um relatório relacionado ao Plano Educacional Individualizado, quando aplicável, e sugestões para a família.&lt;/p&gt;

&lt;p&gt;O backend reúne avaliações, boletins, observações, registros pedagógicos e documentos institucionais. Comecei a investigar RAG porque suspeitava que estava enviando informações demais aos modelos.&lt;/p&gt;

&lt;p&gt;A análise da implementação trouxe uma situação mais interessante: alguns prompts recebiam documentos completos, enquanto determinadas evidências pedagógicas não estavam sendo carregadas ou incluídas corretamente.&lt;/p&gt;

&lt;p&gt;Ou seja, o contexto podia ser extenso e, ao mesmo tempo, insuficiente para a tarefa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Duas necessidades diferentes de acesso à informação
&lt;/h3&gt;

&lt;p&gt;Os dados do aluno já pertencem a uma matrícula, uma instituição e um período conhecidos. Não preciso procurar por similaridade qual boletim ou avaliação utilizar. Preciso consultar corretamente os registros e preservar as evidências obrigatórias.&lt;/p&gt;

&lt;p&gt;Os documentos institucionais apresentam outra possibilidade. Diretrizes e orientações poderiam ser recuperadas conforme a finalidade do relatório. Porém, o diagnóstico indicou alternativas anteriores: melhorar filtros, selecionar documentos pertinentes e avaliar orientações resumidas e revisadas.&lt;/p&gt;

&lt;p&gt;Por isso, decidi não adicionar recuperação documental neste momento. A prioridade é corrigir a montagem do contexto e criar uma seleção específica para cada relatório.&lt;/p&gt;

&lt;p&gt;Essa conclusão vale para o fluxo analisado. Uma aplicação educacional com um acervo extenso e perguntas abertas sobre documentos poderia apresentar uma necessidade diferente.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que ainda precisa ser medido
&lt;/h3&gt;

&lt;p&gt;A análise foi feita a partir do código. Ainda não há economia ou melhoria de qualidade comprovada.&lt;/p&gt;

&lt;p&gt;As mudanças precisam ser comparadas usando casos equivalentes, medindo consumo, latência, completude e fidelidade. Corrigir a ausência de evidências pode aumentar os tokens em algumas seções e, ainda assim, ser uma melhoria necessária.&lt;/p&gt;

&lt;p&gt;Se os documentos institucionais continuarem representando um problema depois dessas correções, a recuperação poderá ser reavaliada com critérios mais claros.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Quando vale considerar RAG?
&lt;/h2&gt;

&lt;p&gt;RAG merece investigação quando a geração depende de conhecimento externo e existe uma necessidade real de selecionar esse conteúdo: um acervo grande, documentos distribuídos ou perguntas cujo contexto varia bastante.&lt;/p&gt;

&lt;p&gt;Também pode ser útil quando precisamos atualizar fontes sem retreinar o modelo e preservar a origem das informações usadas nas respostas.&lt;/p&gt;

&lt;p&gt;Antes de implementar, vale perguntar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Que informação a solicitação exige?&lt;/li&gt;
&lt;li&gt;Sabemos exatamente onde buscá-la ou precisamos pesquisar um acervo?&lt;/li&gt;
&lt;li&gt;Quais evidências são obrigatórias?&lt;/li&gt;
&lt;li&gt;Como os documentos mudam e como as permissões são aplicadas?&lt;/li&gt;
&lt;li&gt;Como saberemos se a recuperação melhorou a resposta?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As respostas ajudam a escolher entre consultas diretas, seleção determinística, busca documental ou uma combinação dessas estratégias.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;RAG conecta a geração de linguagem a informações recuperadas para uma solicitação. Essa ideia abre possibilidades importantes, mas sua qualidade depende de várias decisões: preparar as fontes, preservar contexto, encontrar evidências, aplicar permissões e avaliar as respostas.&lt;/p&gt;

&lt;p&gt;Embeddings e bancos vetoriais são ferramentas possíveis dentro dessa arquitetura. A escolha começa pelo tipo de informação e pela forma como ela precisa ser acessada.&lt;/p&gt;

&lt;p&gt;Na minha aplicação, estudar RAG ajudou a identificar uma prioridade anterior: construir melhor o contexto obtido por consultas que já eram conhecidas. Em outro cenário, a recuperação pode ser justamente a parte que falta.&lt;/p&gt;

&lt;p&gt;Entender o mecanismo permite fazer essa distinção e adotar a tecnologia com um problema definido e uma forma de verificar o resultado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2005.11401" rel="noopener noreferrer"&gt;Lewis et al. — Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/engineering/contextual-retrieval" rel="noopener noreferrer"&gt;Anthropic — Contextual Retrieval&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aclanthology.org/2024.tacl-1.9/" rel="noopener noreferrer"&gt;Liu et al. — Lost in the Middle: How Language Models Use Long Contexts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>Stack, Heap e memória: por que isso ainda importa para quem programa em JavaScript?</title>
      <dc:creator>Lucas Henrique Alves Rosa</dc:creator>
      <pubDate>Sat, 17 Oct 2026 21:47:21 +0000</pubDate>
      <link>https://dev.to/lucasharosa/stack-heap-e-memoria-por-que-isso-ainda-importa-para-quem-programa-em-javascript-h30</link>
      <guid>https://dev.to/lucasharosa/stack-heap-e-memoria-por-que-isso-ainda-importa-para-quem-programa-em-javascript-h30</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que muda entre essas duas alocações?&lt;/p&gt;

&lt;p&gt;Se você já programou em C, provavelmente lembrou de stack, heap, ponteiros e da necessidade de chamar &lt;code&gt;free&lt;/code&gt;. Se trabalha principalmente com JavaScript, talvez tenha pensado: “ainda bem que não preciso cuidar disso”.&lt;/p&gt;

&lt;p&gt;O JavaScript realmente abstrai boa parte desse trabalho. Mas entender memória continua ajudando a explicar por que dois objetos mudam juntos, por que uma cópia não ficou independente ou por que uma aplicação mantém dados que já deveriam ter sido descartados.&lt;/p&gt;

&lt;p&gt;Este é o terceiro artigo da série &lt;strong&gt;“Coisas que usamos todos os dias, mas raramente paramos para entender.”&lt;/strong&gt; Depois de explorar o DOM e o Event Loop, vamos olhar para o que sustenta os dados usados pelo nosso código: a memória.&lt;/p&gt;

&lt;p&gt;A ideia é começar em C, onde algumas responsabilidades ficam explícitas, e conectar esses conceitos ao JavaScript com exemplos para reproduzir.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Antes de tudo: o que significa alocar memória?
&lt;/h2&gt;

&lt;p&gt;Durante a execução de um programa, seus dados precisam ser representados em algum lugar. &lt;strong&gt;Alocar memória&lt;/strong&gt; significa disponibilizar espaço para armazená-los; usar essa memória envolve ler e escrever valores; desalocar significa tornar o espaço disponível para reutilização.&lt;/p&gt;

&lt;p&gt;Isso não significa necessariamente apagar os bytes imediatamente ou devolver memória ao sistema operacional naquele instante. São coisas diferentes: um alocador pode manter regiões disponíveis para atender a futuras solicitações do próprio processo.&lt;/p&gt;

&lt;p&gt;Também precisamos separar dois conceitos que aparecem juntos com frequência:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escopo:&lt;/strong&gt; em que parte do código um nome pode ser acessado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifetime, ou tempo de vida:&lt;/strong&gt; durante qual período um objeto existe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Um nome deixar de estar acessível em determinado trecho não significa, por si só, que todos os dados associados a ele deixaram de existir. Essa distinção será importante quando chegarmos aos objetos e às closures em JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Voltando ao exemplo em C
&lt;/h2&gt;

&lt;p&gt;Vamos colocar o código dentro de uma função e tratar uma condição importante: &lt;code&gt;malloc&lt;/code&gt; pode falhar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui temos três coisas que precisam ser distinguidas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Elemento&lt;/th&gt;
&lt;th&gt;O que representa&lt;/th&gt;
&lt;th&gt;Tempo de vida neste exemplo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;age&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Um objeto do tipo &lt;code&gt;int&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Duração automática, associada à execução do bloco&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uma variável do tipo ponteiro para &lt;code&gt;int&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Também tem duração automática&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Espaço obtido por &lt;code&gt;malloc&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Armazenamento para o inteiro acessado por &lt;code&gt;*value&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Permanece alocado até &lt;code&gt;free&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Portanto, não temos simplesmente “uma variável na stack e outra no heap”. Temos uma variável inteira, uma variável ponteiro e uma alocação dinâmica acessada por esse ponteiro.&lt;/p&gt;

&lt;p&gt;Em implementações comuns, variáveis locais como essas podem ficar na stack, enquanto &lt;code&gt;malloc&lt;/code&gt; fornece memória de uma região chamada heap. Mas a linguagem C descreve essas diferenças por meio de duração de armazenamento e regras de uso, sem exigir esse posicionamento físico específico. O compilador também pode manter valores em registradores ou eliminar armazenamento por otimização.&lt;/p&gt;

&lt;p&gt;Para entender o exemplo, a diferença mais importante é &lt;strong&gt;quem controla o tempo de vida do armazenamento&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Stack: memória ligada às chamadas de função
&lt;/h2&gt;

&lt;p&gt;No artigo sobre Event Loop, usamos a call stack para acompanhar chamadas de função. Em implementações comuns, cada chamada pode ter uma estrutura chamada &lt;strong&gt;stack frame&lt;/strong&gt;, que mantém informações necessárias para executar a função e retornar à anterior.&lt;/p&gt;

&lt;p&gt;Dependendo da implementação e das otimizações, esse frame pode conter parâmetros, variáveis locais e valores temporários.&lt;/p&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;mostrarIdade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O objeto local &lt;code&gt;age&lt;/code&gt; tem duração automática. Não precisamos chamar &lt;code&gt;free&lt;/code&gt; para ele: seu tempo de vida termina quando saímos do bloco correspondente.&lt;/p&gt;

&lt;p&gt;Esse modelo combina com a organização de uma pilha: chamadas entram e, ao retornar, deixam de precisar de suas informações de execução.&lt;/p&gt;

&lt;p&gt;Mas isso também traz limites. Se uma sequência de chamadas cresce demais, como numa recursão sem condição de parada, podemos esgotar o espaço disponível para a pilha.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack e heap não são duas categorias de tipos de dados.&lt;/strong&gt; São conceitos relacionados à organização da memória e da execução.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Heap: armazenamento com tempo de vida independente da chamada
&lt;/h2&gt;

&lt;p&gt;Agora imagine que precisamos criar um valor em uma função e utilizá-lo depois que ela retornar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;criarValor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A variável local &lt;code&gt;value&lt;/code&gt; deixa de existir ao terminar a função. Mas o armazenamento obtido por &lt;code&gt;malloc&lt;/code&gt; continua alocado, e a função retorna o ponteiro necessário para acessá-lo.&lt;/p&gt;

&lt;p&gt;Quem recebe esse ponteiro precisa assumir a responsabilidade pela liberação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;criarValor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse é um dos motivos para usar alocação dinâmica: o armazenamento pode continuar existindo além da chamada que o solicitou.&lt;/p&gt;

&lt;p&gt;Se perdemos todos os ponteiros necessários para liberar uma alocação, ela pode continuar ocupando memória sem que o programa consiga recuperá-la pelo caminho esperado. Esse é um exemplo de vazamento de memória.&lt;/p&gt;

&lt;p&gt;Também existe o problema contrário: acessar o armazenamento depois de liberá-lo. Em C, isso resulta em comportamento indefinido.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Endereço, ponteiro e valor são coisas diferentes
&lt;/h2&gt;

&lt;p&gt;Podemos pensar em um endereço como uma forma de identificar uma localização no espaço de memória do processo. Um ponteiro permite referenciar um objeto por meio dessa localização.&lt;/p&gt;

&lt;p&gt;No exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agePointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agePointer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os símbolos têm papéis diferentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;age&lt;/code&gt; obtém o endereço de &lt;code&gt;age&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agePointer&lt;/code&gt; guarda um ponteiro para esse objeto.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*agePointer&lt;/code&gt; acessa o inteiro apontado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assim, podemos modificar o mesmo objeto por outro caminho:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;agePointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não criamos uma segunda idade independente. Criamos outra forma de acessar a original.&lt;/p&gt;

&lt;p&gt;Também vale reparar que &lt;code&gt;sizeof *value&lt;/code&gt;, usado anteriormente, consulta o tamanho do tipo apontado. Nesse caso, ele não precisa ler o conteúdo da memória apontada para descobrir esse tamanho.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. E quando escrevemos um objeto em JavaScript?
&lt;/h2&gt;

&lt;p&gt;Em JavaScript, fazemos isto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não solicitamos um número de bytes nem recebemos um ponteiro manipulável como em C. O motor cuida da representação e da alocação.&lt;/p&gt;

&lt;p&gt;Isso costuma ser explicado com a frase “primitivos ficam na stack e objetos ficam no heap”. Ela pode servir como um desenho inicial, mas não deve ser tratada como uma regra da linguagem.&lt;/p&gt;

&lt;p&gt;O JavaScript não determina que todo número precise estar na stack ou que toda variável local tenha uma posição fixa ali. Motores como o V8 usam diferentes representações e otimizações.&lt;/p&gt;

&lt;p&gt;Para quem está escrevendo a aplicação, o comportamento observável é mais útil: &lt;strong&gt;o objeto tem identidade e pode ser compartilhado por diferentes variáveis&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anotherUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;anotherUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Ana"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;anotherUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A atribuição não criou um segundo objeto. As duas variáveis permitem acessar o mesmo objeto.&lt;/p&gt;

&lt;p&gt;Aqui usamos “referência” para explicar esse acesso compartilhado. Não significa que o JavaScript nos entregue um endereço de memória que podemos somar, imprimir ou liberar manualmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;code&gt;const&lt;/code&gt; não torna o objeto imutável
&lt;/h2&gt;

&lt;p&gt;No exemplo anterior, declaramos &lt;code&gt;user&lt;/code&gt; com &lt;code&gt;const&lt;/code&gt;, mas conseguimos modificar sua propriedade. Isso acontece porque &lt;code&gt;const&lt;/code&gt; impede a reatribuição da variável, não alterações no conteúdo do objeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Permitido.&lt;/span&gt;

&lt;span class="c1"&gt;// user = { name: "Mariana" };&lt;/span&gt;
&lt;span class="c1"&gt;// TypeError: não podemos reatribuir essa variável.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa diferença importa ao compartilhar objetos entre funções, componentes e serviços. Uma variável constante não garante que o objeto acessado por ela permanecerá igual.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Passar um objeto para uma função não cria uma cópia
&lt;/h2&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;atualizarNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;atualizarNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Ana"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função acessa o mesmo objeto e altera uma propriedade dele.&lt;/p&gt;

&lt;p&gt;Mas observe o que acontece se reatribuirmos o parâmetro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;substituirUsuario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mariana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;substituirUsuario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Lucas"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript passa argumentos por valor. No caso de um objeto, o valor passado permite acessar o mesmo objeto; não é uma cópia independente de seu conteúdo. Reatribuir o parâmetro muda apenas a variável local da função.&lt;/p&gt;

&lt;p&gt;Essa distinção explica por que alterar uma propriedade pode afetar o chamador, enquanto substituir o parâmetro não substitui sua variável original.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Spread faz uma cópia, mas ela é superficial
&lt;/h2&gt;

&lt;p&gt;Uma tentativa comum de criar um objeto independente é usar spread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Brasília&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Goiânia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Lucas"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Goiânia"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O objeto externo foi copiado, mas o objeto &lt;code&gt;address&lt;/code&gt; continua compartilhado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa é uma &lt;strong&gt;cópia superficial&lt;/strong&gt;: os valores das propriedades são copiados, sem duplicar recursivamente os objetos aninhados.&lt;/p&gt;

&lt;p&gt;Para alterar a cidade preservando o objeto original, podemos copiar também o nível que será modificado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;São Paulo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso aparece diretamente em atualizações de estado no React. Entender identidade e compartilhamento ajuda a evitar mutações acidentais, sem precisar decorar que “sempre tem que espalhar tudo”.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Garbage Collector: quem libera a memória em JavaScript?
&lt;/h2&gt;

&lt;p&gt;JavaScript usa gerenciamento automático de memória. O Garbage Collector, ou GC, identifica armazenamento que pode ser recuperado.&lt;/p&gt;

&lt;p&gt;Uma ideia central é a &lt;strong&gt;alcançabilidade&lt;/strong&gt;: se um objeto ainda pode ser acessado a partir das raízes consideradas pelo motor, diretamente ou por uma cadeia de referências, ele permanece alcançável.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;selectedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O objeto continua acessível por &lt;code&gt;selectedUser&lt;/code&gt;. Atribuir &lt;code&gt;null&lt;/code&gt; a &lt;code&gt;user&lt;/code&gt; não o libera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;selectedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se não houver outro caminho que mantenha esse objeto alcançável, ele poderá ser coletado. Isso não determina o instante da coleta.&lt;/p&gt;

&lt;p&gt;Coletores modernos também conseguem lidar com ciclos de referências. Dois objetos apontarem um para o outro não impede, por si só, a coleta se o conjunto se tornar inalcançável.&lt;/p&gt;

&lt;p&gt;O V8 combina técnicas de coleta, incluindo processamento geracional e trabalho incremental, paralelo ou concorrente. Isso reduz determinados custos, mas não torna a administração da memória gratuita.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Uma função terminar não significa que seus dados desapareceram
&lt;/h2&gt;

&lt;p&gt;Closures deixam essa diferença bastante visível:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;criarContador&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;incrementar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;criarContador&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;contador&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;contador&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A chamada de &lt;code&gt;criarContador&lt;/code&gt; terminou, mas a função retornada continua acessando &lt;code&gt;total&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Uma closure mantém acesso ao ambiente léxico relevante para sua execução. Por isso, dados necessários à função podem continuar disponíveis depois que a chamada externa retorna.&lt;/p&gt;

&lt;p&gt;Isso não significa que o stack frame inteiro precise ficar preservado ou que todas as variáveis daquela função sejam necessariamente mantidas. A implementação pode otimizar essa representação.&lt;/p&gt;

&lt;p&gt;Closures são um recurso importante da linguagem. O cuidado é perceber quando uma função que permanece acessível também mantém dados de que já não precisamos.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Um exemplo prático: um cache que nunca esquece
&lt;/h2&gt;

&lt;p&gt;Imagine um serviço Node.js que mantém relatórios em memória:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reportsCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cacheReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;reportsCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;reportsCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se esse Map continuar acessível e receber novos IDs indefinidamente, os relatórios armazenados continuam alcançáveis. O GC não sabe que um relatório antigo deixou de ter utilidade para o negócio.&lt;/p&gt;

&lt;p&gt;Podemos explicitar sua remoção:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;removeReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;reportsCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso remove o caminho de acesso pelo cache. Se outro trecho ainda mantiver o relatório, ele continuará acessível por lá.&lt;/p&gt;

&lt;p&gt;Uma política real pode usar limite de entradas, expiração com remoção efetiva ou descarte dos itens menos utilizados. Apenas registrar uma data de expiração não libera nada se as entradas continuarem armazenadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O GC cuida da recuperação automática; a aplicação continua responsável por decidir o que precisa permanecer acessível.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Como investigar isso na prática?
&lt;/h2&gt;

&lt;p&gt;Para investigar uma suspeita de retenção no navegador, podemos reproduzir repetidamente uma ação, abrir e fechar uma tela, por exemplo, e comparar heap snapshots no DevTools.&lt;/p&gt;

&lt;p&gt;O objetivo é observar quais objetos continuam retidos e quais caminhos os mantêm acessíveis. O tamanho de um objeto isolado pode ser pequeno, mas suas referências podem manter uma estrutura muito maior.&lt;/p&gt;

&lt;p&gt;Também precisamos interpretar o comportamento com cuidado. A memória não precisa cair imediatamente depois de uma ação, e subir temporariamente não prova um vazamento. O motor pode adiar a coleta e reutilizar espaço já reservado.&lt;/p&gt;

&lt;p&gt;A pergunta útil é: &lt;strong&gt;depois de repetir o fluxo, estamos mantendo cada vez mais dados que já deveriam ter sido descartados?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O exemplo em C mostra responsabilidades que ficam menos visíveis em JavaScript: obter armazenamento, acessar dados e controlar seu tempo de vida. Stack, heap, ponteiros e referências ajudam a construir esse entendimento, desde que não confundamos um modelo didático com as garantias de cada linguagem.&lt;/p&gt;

&lt;p&gt;No JavaScript, esses fundamentos aparecem quando duas variáveis compartilham um objeto, uma cópia superficial mantém dados aninhados em comum, uma closure preserva acesso a um valor ou um cache retém informações indefinidamente.&lt;/p&gt;

&lt;p&gt;Não precisamos administrar cada byte para tomar decisões melhores sobre memória. Precisamos entender o que estamos compartilhando, por quanto tempo os dados continuam acessíveis e quais referências deixaram de ser necessárias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linguagens modernas escondem a administração da memória; elas não fazem a memória desaparecer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Você já investigou um problema que parecia ser de performance, mas estava relacionado a dados mantidos em memória por mais tempo do que deveriam?&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Memory_management" rel="noopener noreferrer"&gt;MDN — Memory management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions" rel="noopener noreferrer"&gt;MDN — Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy" rel="noopener noreferrer"&gt;MDN — Shallow copy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures" rel="noopener noreferrer"&gt;MDN — Closures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v8.dev/blog/pointer-compression" rel="noopener noreferrer"&gt;V8 — Pointer Compression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://v8.dev/blog/trash-talk" rel="noopener noreferrer"&gt;V8 — Trash talk: the Orinoco garbage collector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>computerscience</category>
      <category>javascript</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Event Loop: como JavaScript executa código assíncrono?</title>
      <dc:creator>Lucas Henrique Alves Rosa</dc:creator>
      <pubDate>Wed, 14 Oct 2026 14:00:25 +0000</pubDate>
      <link>https://dev.to/lucasharosa/event-loop-como-javascript-executa-codigo-assincrono-3idp</link>
      <guid>https://dev.to/lucasharosa/event-loop-como-javascript-executa-codigo-assincrono-3idp</guid>
      <description>&lt;h3&gt;
  
  
  Analise o código abaixo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Qual é a ordem?&lt;/p&gt;

&lt;p&gt;Se você pensou em &lt;code&gt;A, B, C, D&lt;/code&gt;, faz sentido: é a ordem em que escrevemos o código. Mas não é a ordem em que todas essas funções executam.&lt;/p&gt;

&lt;p&gt;Este é o segundo artigo da série &lt;strong&gt;“Coisas que usamos todos os dias, mas raramente paramos para entender.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A ideia é escolher conceitos que aparecem no meu trabalho, estudar com mais profundidade e registrar o que aprendi. Escrever também me ajuda a testar meu entendimento e encontrar dúvidas que passariam despercebidas.&lt;/p&gt;

&lt;p&gt;Depois de explorar o DOM e as atualizações de interface, quero entender melhor o que acontece quando misturamos código síncrono, timers e Promises.&lt;/p&gt;

&lt;p&gt;Vamos partir desse exemplo e acompanhar sua execução.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Antes das filas, precisamos falar do runtime
&lt;/h2&gt;

&lt;p&gt;Quando executamos JavaScript, temos duas partes trabalhando juntas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engine:&lt;/strong&gt; interpreta e executa a linguagem. O V8, usado no Chrome e no Node.js, é um exemplo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ambiente hospedeiro:&lt;/strong&gt; oferece recursos para interagir com o mundo externo, como timers, rede e eventos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chamamos de &lt;strong&gt;runtime&lt;/strong&gt; o ambiente de execução formado por esses mecanismos.&lt;/p&gt;

&lt;p&gt;No navegador, temos APIs como DOM e &lt;code&gt;setTimeout&lt;/code&gt;. No Node.js, temos recursos como acesso ao sistema de arquivos e APIs de rede.&lt;/p&gt;

&lt;p&gt;Essa distinção importa porque nem tudo que usamos num programa JavaScript pertence à linguagem.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Promise&lt;/code&gt; faz parte do JavaScript. &lt;code&gt;setTimeout&lt;/code&gt; é disponibilizado pelo ambiente.&lt;/p&gt;

&lt;p&gt;O funcionamento assíncrono depende da cooperação entre essas partes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Call stack: o que está executando agora?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;call stack&lt;/strong&gt;, ou pilha de chamadas, acompanha os contextos de execução.&lt;/p&gt;

&lt;p&gt;Quando uma função chama outra, a execução da segunda fica no topo da pilha. Ao terminar, ela sai, e a primeira continua.&lt;/p&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mostrarMensagem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Olá!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;iniciar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;mostrarMensagem&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;iniciar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sequência é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O código chama &lt;code&gt;iniciar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iniciar&lt;/code&gt; chama &lt;code&gt;mostrarMensagem&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mostrarMensagem&lt;/code&gt; chama &lt;code&gt;console.log&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As chamadas terminam, devolvendo o controle às anteriores.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A pilha segue a regra &lt;strong&gt;último a entrar, primeiro a sair&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na mesma thread de execução, um callback assíncrono não interrompe uma função JavaScript no meio para começar a executar.&lt;/p&gt;

&lt;p&gt;Por isso, se uma função fica ocupada com um cálculo longo, os callbacks que dependem dessa thread precisam esperar.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Assíncrono não significa executar tudo ao mesmo tempo
&lt;/h2&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Antes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Timer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Depois&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O programa não fica parado durante um segundo dentro de &lt;code&gt;setTimeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ele registra um timer no ambiente e continua executando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Antes
Depois
Timer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O callback fica para depois.&lt;/p&gt;

&lt;p&gt;O ambiente pode acompanhar operações fora da execução atual do JavaScript. Quando existe trabalho pronto para continuar, os mecanismos de agendamento determinam quando seu callback pode executar.&lt;/p&gt;

&lt;p&gt;Isso permite lidar com várias operações em andamento sem executar todos os callbacks simultaneamente na mesma thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Task queue e microtask queue
&lt;/h2&gt;

&lt;p&gt;No navegador, precisamos distinguir dois tipos de trabalho.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tasks
&lt;/h3&gt;

&lt;p&gt;Uma &lt;strong&gt;task&lt;/strong&gt; é uma unidade de trabalho agendada pelo ambiente. A execução de um callback de timer é um exemplo.&lt;/p&gt;

&lt;p&gt;É comum encontrar o termo &lt;strong&gt;macrotask&lt;/strong&gt; em explicações sobre o assunto, mas aqui vou usar &lt;strong&gt;task&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Também falamos em &lt;em&gt;task queue&lt;/em&gt;, ou fila de tarefas. É uma simplificação útil, mas o navegador pode ter diferentes filas e fontes de tarefas, não uma única fila universal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microtasks
&lt;/h3&gt;

&lt;p&gt;As &lt;strong&gt;microtasks&lt;/strong&gt; são processadas em pontos específicos chamados de &lt;em&gt;microtask checkpoints&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Elas incluem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As reações de Promises, como os callbacks de &lt;code&gt;.then&lt;/code&gt;, &lt;code&gt;.catch&lt;/code&gt; e &lt;code&gt;.finally&lt;/code&gt;, quando podem executar.&lt;/li&gt;
&lt;li&gt;Funções agendadas com &lt;code&gt;queueMicrotask&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A continuação de uma função após um &lt;code&gt;await&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para o nosso exemplo, a regra importante é:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quando a execução síncrona atual termina, as microtasks pendentes são processadas antes do callback do timer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se uma microtask agenda outra, a nova também pode executar nesse mesmo processamento, antes de passar para a próxima task.&lt;/p&gt;

&lt;p&gt;Isso não significa que uma Promise interrompa o código que já está executando.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Então o que o Event Loop faz?
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Event Loop&lt;/strong&gt; coordena o processamento do trabalho agendado pelo ambiente.&lt;/p&gt;

&lt;p&gt;Para entender o exemplo inicial no navegador, podemos usar este modelo simplificado:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Executar o trabalho JavaScript atual até terminar.&lt;/li&gt;
&lt;li&gt;Processar as microtasks pendentes.&lt;/li&gt;
&lt;li&gt;Permitir que o ambiente continue seu ciclo e selecione outra task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O navegador também precisa encaixar oportunidades de atualização visual nesse ciclo. Não existe a garantia de que ele desenhe a tela depois de toda task.&lt;/p&gt;

&lt;p&gt;O Event Loop não torna os callbacks paralelos. Ele ajuda a organizar &lt;strong&gt;quando cada trabalho pode executar&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Vamos reproduzir o exemplo
&lt;/h2&gt;

&lt;p&gt;Crie um arquivo chamado &lt;code&gt;index.html&lt;/code&gt;, cole este código e abra no navegador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"pt-BR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Event Loop&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Event Loop&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Abra o console do navegador para acompanhar a execução.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abra o DevTools e a aba &lt;strong&gt;Console&lt;/strong&gt;. Se necessário, recarregue a página.&lt;/p&gt;

&lt;p&gt;O resultado será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
C
B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos entender cada etapa.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Por que a ordem é A, D, C, B?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Primeiro: A
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É uma chamada síncrona. Executa naquele momento.&lt;/p&gt;

&lt;p&gt;Saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Depois: registramos o timer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O ambiente registra o timer.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;0&lt;/code&gt; não significa “execute agora”. A execução ainda depende das regras do ambiente e da disponibilidade para processar o callback.&lt;/p&gt;

&lt;p&gt;Portanto, &lt;code&gt;B&lt;/code&gt; ainda não aparece.&lt;/p&gt;

&lt;h3&gt;
  
  
  Depois: agendamos a reação da Promise
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Promise.resolve()&lt;/code&gt; retorna, neste caso, uma Promise já cumprida.&lt;/p&gt;

&lt;p&gt;Mesmo assim, o callback passado para &lt;code&gt;.then&lt;/code&gt; não executa imediatamente. Sua execução é agendada como uma microtask.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C&lt;/code&gt; também ainda não aparece.&lt;/p&gt;

&lt;h3&gt;
  
  
  Depois: D
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outra chamada síncrona. O código atual ainda está executando, então imprime &lt;code&gt;D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Saída até aqui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A execução síncrona termina: C
&lt;/h3&gt;

&lt;p&gt;Agora a microtask da Promise pode ser processada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O callback do timer executa: B
&lt;/h3&gt;

&lt;p&gt;Quando o callback do timer é processado como uma task, imprime &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Resultado final:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
C
B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ordem em que escrevemos o código não determina, sozinha, a ordem dos callbacks.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trecho&lt;/th&gt;
&lt;th&gt;Tipo de trabalho&lt;/th&gt;
&lt;th&gt;Resultado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log("A")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Síncrono&lt;/td&gt;
&lt;td&gt;Executa primeiro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Registra um timer&lt;/td&gt;
&lt;td&gt;Seu callback fica para depois&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.then(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agenda uma reação da Promise&lt;/td&gt;
&lt;td&gt;Executa como microtask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;console.log("D")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Síncrono&lt;/td&gt;
&lt;td&gt;Executa antes dos callbacks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  8. Um detalhe: nem tudo dentro de uma Promise é assíncrono
&lt;/h2&gt;

&lt;p&gt;Considere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
B
D
C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função passada ao construtor de &lt;code&gt;Promise&lt;/code&gt;, chamada de &lt;strong&gt;executor&lt;/strong&gt;, executa imediatamente.&lt;/p&gt;

&lt;p&gt;Já a reação registrada pelo &lt;code&gt;.then&lt;/code&gt; executa depois, como microtask.&lt;/p&gt;

&lt;p&gt;Portanto, colocar um cálculo pesado dentro de &lt;code&gt;new Promise&lt;/code&gt; não faz esse cálculo sair da thread atual.&lt;/p&gt;

&lt;p&gt;Uma Promise representa um resultado que pode estar pendente, ser cumprido ou ser rejeitado. Ela não cria automaticamente uma thread para executar seu código.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Onde o async/await entra?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;async/await&lt;/code&gt; permite escrever código baseado em Promises com uma leitura mais sequencial.&lt;/p&gt;

&lt;p&gt;Vamos testar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;executar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
B
D
C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que aconteceu?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; é impresso.&lt;/li&gt;
&lt;li&gt;Chamamos &lt;code&gt;executar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A função imprime &lt;code&gt;B&lt;/code&gt; de forma síncrona.&lt;/li&gt;
&lt;li&gt;Ao chegar no &lt;code&gt;await&lt;/code&gt;, a função suspende sua execução.&lt;/li&gt;
&lt;li&gt;O código que chamou a função continua e imprime &lt;code&gt;D&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A continuação após o &lt;code&gt;await&lt;/code&gt; é processada depois e imprime &lt;code&gt;C&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;O &lt;code&gt;await&lt;/code&gt; suspende aquela função; ele não bloqueia a thread inteira.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mesmo esperando uma Promise já cumprida, a continuação após o &lt;code&gt;await&lt;/code&gt; acontece de forma assíncrona.&lt;/p&gt;

&lt;p&gt;Uma função &lt;code&gt;async&lt;/code&gt; também retorna uma Promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;obterNumero&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;obterNumero&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;numero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numero&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas isso não torna todo o seu corpo assíncrono. O código anterior ao primeiro &lt;code&gt;await&lt;/code&gt; executa durante a chamada da função.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. setTimeout com zero não é execução imediata
&lt;/h2&gt;

&lt;p&gt;Podemos observar isso com uma espera ocupada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Timer executou após:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Mantém a thread ocupada por aproximadamente 200 ms.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Código síncrono terminou&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O timer só poderá executar depois que o código síncrono liberar a thread.&lt;/p&gt;

&lt;p&gt;Você verá algo parecido com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Código síncrono terminou
Timer executou após: 201 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O tempo exato varia. O ponto é que o timer não interrompeu o &lt;code&gt;while&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esse loop é apenas uma demonstração. Durante sua execução no navegador, a thread principal fica ocupada, prejudicando interações e atualizações da página.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Como isso aparece no trabalho?
&lt;/h2&gt;

&lt;p&gt;No frontend, cálculos longos na thread principal podem atrasar respostas aos cliques e atualizações visuais.&lt;/p&gt;

&lt;p&gt;No backend Node.js, cálculos longos na thread do Event Loop podem atrasar o processamento de outras requisições e callbacks.&lt;/p&gt;

&lt;p&gt;Uma função marcada como &lt;code&gt;async&lt;/code&gt; continua podendo bloquear essa thread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executarCalculoPesado&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simula trabalho síncrono.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Concluído&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calcular&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;executarCalculoPesado&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicionar &lt;code&gt;async&lt;/code&gt; não transfere o cálculo para outro lugar. Ao chamar &lt;code&gt;calcular()&lt;/code&gt;, o cálculo síncrono executa antes de a chamada retornar sua Promise.&lt;/p&gt;

&lt;p&gt;Dependendo do problema, precisamos reduzir o trabalho, dividi-lo em etapas que permitam ao ambiente continuar ou usar mecanismos como Web Workers no navegador e worker threads no Node.js.&lt;/p&gt;

&lt;p&gt;Também vale ter cuidado com microtasks que continuam criando outras microtasks. Uma sequência longa pode atrasar tasks e, no navegador, oportunidades de atualização visual.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. E no Node.js?
&lt;/h2&gt;

&lt;p&gt;O exemplo inicial também produz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
C
B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode salvar o código em &lt;code&gt;event-loop.cjs&lt;/code&gt; e executar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node event-loop.cjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas não devemos concluir que navegador e Node.js têm exatamente o mesmo agendamento.&lt;/p&gt;

&lt;p&gt;O Node.js organiza seu Event Loop em fases e possui mecanismos próprios, como &lt;code&gt;process.nextTick&lt;/code&gt; e &lt;code&gt;setImmediate&lt;/code&gt;. Esses detalhes podem afetar comparações de ordem em exemplos mais complexos.&lt;/p&gt;

&lt;p&gt;Para este artigo, vale guardar o fundamento comum: o código síncrono atual precisa terminar antes de esses callbacks assíncronos executarem.&lt;/p&gt;

&lt;p&gt;Vou deixar as fases do Node.js e o papel da libuv para um próximo artigo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O exemplo de quatro letras ajuda a separar três coisas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O código que executa agora.&lt;/li&gt;
&lt;li&gt;O trabalho agendado como microtask.&lt;/li&gt;
&lt;li&gt;O trabalho que depende de uma task futura, como o callback do timer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É por isso que chegamos a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A
D
C
B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entender essa divisão me ajuda a investigar uma atualização que demorou, uma sequência de callbacks inesperada ou um cálculo que bloqueou a aplicação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;async/await&lt;/code&gt; simplifica a sintaxe. Ele não elimina o modelo assíncrono que existe por baixo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Você já encontrou um problema em que a ordem de execução era diferente da que parecia olhando o código?&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model" rel="noopener noreferrer"&gt;MDN — JavaScript execution model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide" rel="noopener noreferrer"&gt;MDN — Using microtasks in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="noopener noreferrer"&gt;MDN — async function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick" rel="noopener noreferrer"&gt;Node.js — The Node.js Event Loop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>O que é o DOM e o que o React realmente faz com ele?</title>
      <dc:creator>Lucas Henrique Alves Rosa</dc:creator>
      <pubDate>Fri, 09 Oct 2026 02:59:00 +0000</pubDate>
      <link>https://dev.to/lucasharosa/o-que-e-o-dom-e-o-que-o-react-realmente-faz-com-ele-30d0</link>
      <guid>https://dev.to/lucasharosa/o-que-e-o-dom-e-o-que-o-react-realmente-faz-com-ele-30d0</guid>
      <description>&lt;h1&gt;
  
  
  O que é o DOM e o que o React realmente faz com ele?
&lt;/h1&gt;

&lt;p&gt;Este é o primeiro artigo de uma série que quero escrever: &lt;strong&gt;“Coisas que usamos todos os dias, mas raramente paramos para entender.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A ideia é escolher conceitos que aparecem no meu trabalho, estudar com mais profundidade e registrar o que aprendi. Escrever também é uma forma de testar meu entendimento: quando tento explicar alguma coisa, encontro dúvidas que antes passavam despercebidas.&lt;/p&gt;

&lt;p&gt;Para começar, escolhi algo mais canônico no desenvolvimento web: o DOM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O DOM (Document Object Model, ou Modelo de Objeto de Documento) é uma representação do documento como uma árvore de objetos e nós. Por meio das suas APIs, linguagens como JavaScript podem ler e modificar o conteúdo e a estrutura da página, além de alterar atributos e estilos dos elementos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos pegar um exemplo bem simples. Imagine que você vai fazer seu segundo programa, depois do “Hello, World!”: um botão que conta cliques.&lt;/p&gt;

&lt;p&gt;Cabe uma menção honrosa ao Egg Clicker, pela ideia de tocar em um ovo e acompanhar um contador. Aqui, vamos seguir essa mesma ideia básica e caminhar do HTML até o botão funcionando, com o número de cliques aparecendo na página.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Do HTML para uma árvore de objetos
&lt;/h2&gt;

&lt;p&gt;Considere este HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Contador&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Cliques: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Incrementar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O navegador interpreta a marcação — processo chamado de &lt;strong&gt;parsing&lt;/strong&gt; — e constrói uma estrutura em memória. Essa estrutura é o DOM.&lt;/p&gt;

&lt;p&gt;Mas o que significa dizer que ele é uma “árvore de objetos e nós”?&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é um nó?
&lt;/h3&gt;

&lt;p&gt;Um &lt;strong&gt;nó&lt;/strong&gt; é uma unidade dessa estrutura. Um elemento como &lt;code&gt;main&lt;/code&gt; é um nó. O texto dentro de um elemento também é um nó. Comentários também podem ser nós.&lt;/p&gt;

&lt;p&gt;No contador:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;span id="counter"&amp;gt;&lt;/code&gt; corresponde a um nó de elemento.&lt;/li&gt;
&lt;li&gt;O texto &lt;code&gt;"0"&lt;/code&gt; dentro dele corresponde a um nó de texto.&lt;/li&gt;
&lt;li&gt;O &lt;code&gt;id&lt;/code&gt; é um atributo do elemento; não é um filho na árvore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Portanto, todo elemento é um nó, mas nem todo nó é um elemento.&lt;/p&gt;

&lt;h3&gt;
  
  
  E onde entram os objetos?
&lt;/h3&gt;

&lt;p&gt;O navegador expõe esses nós como objetos, com propriedades e métodos. Quando fazemos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A variável &lt;code&gt;counter&lt;/code&gt; recebe uma referência ao objeto que representa aquele elemento, não uma cópia da sua marcação HTML.&lt;/p&gt;

&lt;p&gt;Podemos consultar esse objeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// "SPAN"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// "counter"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// "0"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// o elemento &amp;lt;p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  E por que uma árvore?
&lt;/h3&gt;

&lt;p&gt;Porque os nós têm relações de parentesco: um nó pode conter filhos, e cada filho ocupa uma posição nessa hierarquia.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;main&lt;/code&gt; contém &lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt; e &lt;code&gt;button&lt;/code&gt;. O &lt;code&gt;p&lt;/code&gt; contém o texto “Cliques:” e o &lt;code&gt;span&lt;/code&gt;. O &lt;code&gt;span&lt;/code&gt; contém o texto “0”.&lt;/p&gt;

&lt;p&gt;Este mapa mostra a parte principal do exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
  body["Elemento: body"] --&amp;gt; main["Elemento: main"]
  main --&amp;gt; h1["Elemento: h1"]
  main --&amp;gt; p["Elemento: p"]
  main --&amp;gt; button["Elemento: button"]
  h1 --&amp;gt; title["Texto: Contador"]
  p --&amp;gt; label["Texto: Cliques:"]
  p --&amp;gt; span["Elemento: span — id counter"]
  span --&amp;gt; value["Texto: 0"]
  button --&amp;gt; action["Texto: Incrementar"]&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;O mapa simplifica a árvore: omite os nós de texto de espaços e quebras de linha. No documento completo, também temos &lt;code&gt;Document&lt;/code&gt;, o doctype, &lt;code&gt;html&lt;/code&gt; e &lt;code&gt;head&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O DOM é a estrutura inteira; os nós são suas partes; a árvore é a organização dessas partes; e os objetos são a forma como acessamos os nós pelo código.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para observar a diferença entre filhos que são elementos e filhos que podem ser qualquer tipo de nó, execute no console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paragraph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// somente elementos filhos&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;childNodes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// inclui nós de texto&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// 1: nó de elemento&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3: nó de texto&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "0", antes dos cliques&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modificar o objeto muda o documento em memória
&lt;/h3&gt;

&lt;p&gt;O DOM oferece APIs para consultar e modificar essa estrutura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não estamos editando o arquivo HTML original. Estamos modificando a representação do documento que o navegador mantém em memória.&lt;/p&gt;

&lt;p&gt;Outro detalhe: o DOM não faz parte da linguagem JavaScript. É uma API disponibilizada pelo navegador. Por isso, &lt;code&gt;document.querySelector&lt;/code&gt; está disponível numa página, mas não faz parte do ambiente padrão do Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Vamos reproduzir o contador com JavaScript
&lt;/h2&gt;

&lt;p&gt;Crie um arquivo chamado &lt;code&gt;index.html&lt;/code&gt;, cole este código e abra o arquivo no navegador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"pt-BR"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Contador com JavaScript&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Contador&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Cliques:
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt; &lt;span class="na"&gt;aria-live=&lt;/span&gt;&lt;span class="s"&gt;"polite"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Incrementar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;script&lt;/code&gt; aparece depois dos elementos que buscamos. Assim, quando ele executa, o navegador já construiu essa parte do DOM.&lt;/p&gt;

&lt;p&gt;Mantive o valor em uma variável, em vez de incrementar diretamente &lt;code&gt;textContent&lt;/code&gt;, para separar duas responsabilidades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; guarda o dado.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;counter.textContent&lt;/code&gt; apresenta esse dado na interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O &lt;code&gt;aria-live="polite"&lt;/code&gt; permite que tecnologias assistivas anunciem a atualização sem interromper imediatamente o que está sendo lido.&lt;/p&gt;

&lt;p&gt;Agora clique algumas vezes no botão. O comportamento é simples, mas vamos observar o que aconteceu.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. O que acontece a cada clique?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;addEventListener&lt;/code&gt; registra uma função para responder ao evento &lt;code&gt;click&lt;/code&gt;. Quando o botão recebe o evento, a função executa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A primeira linha modifica uma variável JavaScript. A segunda modifica o DOM.&lt;/p&gt;

&lt;p&gt;Se você remover a segunda linha, o valor continuará aumentando na memória, mas a página continuará mostrando &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alterar o dado e atualizar sua representação na interface são coisas diferentes.&lt;/strong&gt; Neste exemplo, fazemos essa ligação manualmente.&lt;/p&gt;

&lt;p&gt;Abra o DevTools, encontre o &lt;code&gt;span&lt;/code&gt; na aba &lt;strong&gt;Elements/Elementos&lt;/strong&gt; e clique no botão. Você verá seu conteúdo mudando.&lt;/p&gt;

&lt;p&gt;Podemos confirmar que o elemento foi preservado. Antes de clicar, execute no console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counterBefore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois de alguns cliques:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counterBefore&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O objeto do elemento continua sendo o mesmo. Seu conteúdo mudou.&lt;/p&gt;

&lt;p&gt;Isso não significa que todos os seus filhos foram preservados: atribuir &lt;code&gt;textContent&lt;/code&gt; a um elemento substitui seu conteúdo por texto. É seguro aqui porque o &lt;code&gt;span&lt;/code&gt; foi criado apenas para mostrar o número.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Como a mudança chega à tela?
&lt;/h2&gt;

&lt;p&gt;O DOM representa o documento, mas não é uma imagem pronta.&lt;/p&gt;

&lt;p&gt;O navegador também considera o CSS e realiza o trabalho necessário para apresentar a página:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cálculo de estilos:&lt;/strong&gt; determina as regras aplicáveis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout:&lt;/strong&gt; calcula tamanhos e posições.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paint:&lt;/strong&gt; desenha textos, fundos, bordas e outros detalhes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composição:&lt;/strong&gt; combina as camadas que formam o resultado visual.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nem toda atualização exige todas essas etapas. O trabalho depende da mudança e da estrutura da página.&lt;/p&gt;

&lt;p&gt;Trocar o texto do contador pode afetar a largura do conteúdo e exigir layout. Já outras alterações podem não modificar a geometria dos elementos.&lt;/p&gt;

&lt;p&gt;Além disso, o navegador pode agrupar atualizações antes de apresentar o próximo quadro. Não existe uma relação obrigatória de “uma escrita no DOM = um desenho imediato”.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Por que isso pode ficar caro?
&lt;/h2&gt;

&lt;p&gt;O nosso contador é pequeno. O problema aparece quando a atualização exige muito trabalho ou quando obrigamos o navegador a repeti-lo.&lt;/p&gt;

&lt;p&gt;Um exemplo é intercalar leituras de medidas e alterações de estilo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependendo do layout, a escrita pode invalidar cálculos anteriores. Na próxima volta, a leitura de &lt;code&gt;offsetWidth&lt;/code&gt; pode forçar um novo cálculo para obter a medida atualizada.&lt;/p&gt;

&lt;p&gt;Esse padrão pode causar &lt;strong&gt;layout thrashing&lt;/strong&gt;: cálculos de layout forçados repetidamente.&lt;/p&gt;

&lt;p&gt;Se queremos a largura do container antes das alterações, podemos ler uma vez e depois escrever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa reorganização faz sentido quando a medida capturada é a desejada para todos os cards. Se as escritas mudarem a largura do container e precisarmos de medidas intermediárias, o comportamento será diferente.&lt;/p&gt;

&lt;p&gt;O objetivo é entender o custo das operações e medir quando houver um problema real.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. O mesmo contador em React
&lt;/h2&gt;

&lt;p&gt;Em um projeto React existente, substitua &lt;code&gt;src/App.jsx&lt;/code&gt; por este código. Outra opção é usar um ambiente online com template React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Contador&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Cliques:
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt; &lt;span class="na"&gt;aria-live&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"polite"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Incrementar
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado é o mesmo, mas a responsabilidade mudou.&lt;/p&gt;

&lt;p&gt;No JavaScript puro, dizemos: “Encontre este elemento e altere seu conteúdo”.&lt;/p&gt;

&lt;p&gt;No React, descrevemos: “Para este estado, a interface deve mostrar este conteúdo”.&lt;/p&gt;

&lt;p&gt;A primeira abordagem é &lt;strong&gt;imperativa&lt;/strong&gt;. A segunda é &lt;strong&gt;declarativa&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;JSX descreve a interface; não é uma string de HTML que o React simplesmente cola na página.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Renderização, commit e navegador
&lt;/h2&gt;

&lt;p&gt;Ao clicar, &lt;code&gt;setCount&lt;/code&gt; solicita uma atualização de estado. A função &lt;code&gt;current =&amp;gt; current + 1&lt;/code&gt; calcula o próximo valor a partir do estado pendente.&lt;/p&gt;

&lt;p&gt;O React então calcula a próxima interface executando o componente. Essa etapa é a &lt;strong&gt;renderização do React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Depois, na etapa de &lt;strong&gt;commit&lt;/strong&gt;, o React DOM aplica as alterações necessárias ao DOM real.&lt;/p&gt;

&lt;p&gt;No contador, o texto muda, e os elementos podem ser preservados. O navegador realiza o trabalho visual necessário para mostrar a atualização.&lt;/p&gt;

&lt;p&gt;Por isso, &lt;strong&gt;renderizar novamente não significa recriar o DOM inteiro&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O termo &lt;strong&gt;Virtual DOM&lt;/strong&gt; costuma se referir à representação da interface mantida em memória. A reconciliação compara a nova descrição com a anterior para determinar as atualizações.&lt;/p&gt;

&lt;p&gt;Isso não garante que React seja mais rápido que qualquer implementação manual. Ele também executa código e faz comparações. O benefício está em coordenar a relação entre estado e interface, especialmente conforme a aplicação cresce.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Algumas perguntas interessantes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O componente renderizou novamente?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No contador React, sim: ao incrementar o estado, o React executa o componente novamente para calcular a interface.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No exemplo em JavaScript puro, não existe componente React. Existe a execução do handler e a atualização direta do DOM.&lt;/p&gt;

&lt;p&gt;Para observar a execução do componente, acrescente temporariamente um log dentro da função, antes do &lt;code&gt;return&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App executou com count:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse log indica uma execução, não prova que houve mudança no DOM ou uma imagem nova na tela. Em desenvolvimento, o Strict Mode pode executar o componente mais de uma vez para detectar problemas. Tentativas de renderização também podem ser descartadas.&lt;/p&gt;

&lt;p&gt;Para analisar renderizações com mais detalhe, use o &lt;strong&gt;Profiler do React DevTools&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  O DOM mudou?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sim, nos dois contadores: o conteúdo apresentado pelo span passa de 0 para 1, depois para 2, e assim por diante.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No React, uma nova renderização também pode produzir o mesmo resultado e não exigir alterações no DOM.&lt;/p&gt;

&lt;p&gt;Para observar as mutações no nosso exemplo, execute este código no console antes de clicar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counterObserver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mutação:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Valor:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counterObserver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;subtree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;childList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;characterData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As opções incluem mudanças nos filhos e nos nós de texto, cobrindo formas diferentes de atualizar esse conteúdo. O callback recebe notificações de maneira assíncrona: ele não mede quanto tempo levou para desenhar a tela.&lt;/p&gt;

&lt;p&gt;Para encerrar a observação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counterObserver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você também pode repetir a comparação de referência da seção 3 para confirmar que o elemento &lt;code&gt;span&lt;/code&gt; permaneceu o mesmo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Houve cálculo de layout?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pode haver, mas precisamos observar a execução para afirmar.&lt;/strong&gt; O novo número pode modificar a geometria do texto, especialmente em uma passagem como 9 para 10.&lt;/p&gt;

&lt;p&gt;Um layout também pode ocorrer mesmo sem uma mutação no DOM, por exemplo quando a janela muda de tamanho.&lt;/p&gt;

&lt;p&gt;Para investigar no Chrome:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abra o DevTools e a aba &lt;strong&gt;Performance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Comece uma gravação.&lt;/li&gt;
&lt;li&gt;Clique no contador algumas vezes, incluindo a passagem de 9 para 10.&lt;/li&gt;
&lt;li&gt;Pare a gravação.&lt;/li&gt;
&lt;li&gt;Amplie o intervalo dos cliques e procure eventos como &lt;strong&gt;Recalculate Style&lt;/strong&gt;, &lt;strong&gt;Layout&lt;/strong&gt; e &lt;strong&gt;Paint&lt;/strong&gt; na thread principal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A aba Elements mostra a estrutura. Ela, sozinha, não informa se houve layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Qual dessas etapas está consumindo tempo?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Não dá para concluir apenas lendo o código ou contando renderizações. Precisamos medir a interação.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No contador, esperamos pouco trabalho, mas isso é uma expectativa, não um resultado de benchmark.&lt;/p&gt;

&lt;p&gt;Use duas perspectivas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;O que investigar&lt;/th&gt;
&lt;th&gt;Ferramenta&lt;/th&gt;
&lt;th&gt;O que observar&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cálculo dos componentes React&lt;/td&gt;
&lt;td&gt;React DevTools Profiler&lt;/td&gt;
&lt;td&gt;Componentes renderizados e duração do trabalho de renderização&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript, estilos, layout e desenho&lt;/td&gt;
&lt;td&gt;DevTools Performance&lt;/td&gt;
&lt;td&gt;Eventos, duração e pilha de chamadas no intervalo da interação&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O Profiler do React não mede sozinho todo o custo de layout e paint do navegador. Para medir programaticamente a renderização de uma subárvore, React também oferece o componente &lt;code&gt;Profiler&lt;/code&gt; e o campo &lt;code&gt;actualDuration&lt;/code&gt;; ele não representa o tempo total até a imagem aparecer.&lt;/p&gt;

&lt;p&gt;Se o trabalho estiver concentrado no JavaScript, investigamos o handler e os cálculos dos componentes. Se houver layouts longos ou repetidos, investigamos geometria e leituras de medidas. Se paint dominar, investigamos o trabalho de desenho.&lt;/p&gt;

&lt;p&gt;Logs e observadores são úteis para entender o mecanismo, mas interferem nas medições. Remova a instrumentação didática e considere as diferenças entre desenvolvimento e produção antes de tirar conclusões sobre desempenho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;A parte mais interessante desse contador foi separar coisas que parecem acontecer ao mesmo tempo.&lt;/p&gt;

&lt;p&gt;O JavaScript muda o dado. O DOM representa o documento. O React calcula a interface e coordena suas atualizações. O navegador calcula e desenha o resultado visual.&lt;/p&gt;

&lt;p&gt;Um componente pode renderizar sem mudar o DOM. O DOM pode mudar sem refazer toda a página. E uma mudança pequena pode exigir trabalho de layout dependendo do contexto.&lt;/p&gt;

&lt;p&gt;Entender essas diferenças me ajuda a investigar um problema com mais precisão, em vez de atribuir qualquer lentidão ao “React renderizando demais”.&lt;/p&gt;

&lt;p&gt;É essa a proposta da série: pegar algo cotidiano, reproduzir um exemplo e registrar o que existe por trás.&lt;/p&gt;

&lt;p&gt;Você já precisou investigar uma renderização ou uma atualização do DOM que estava deixando a interface lenta?&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model" rel="noopener noreferrer"&gt;MDN — Document Object Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes" rel="noopener noreferrer"&gt;MDN — Node.childNodes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" rel="noopener noreferrer"&gt;MDN — MutationObserver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/learn/render-and-commit" rel="noopener noreferrer"&gt;React — Render and Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/learn/queueing-a-series-of-state-updates" rel="noopener noreferrer"&gt;React — Queueing a Series of State Updates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/reference/react/Profiler" rel="noopener noreferrer"&gt;React — Profiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/devtools/performance" rel="noopener noreferrer"&gt;Chrome DevTools — Analyze runtime performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing" rel="noopener noreferrer"&gt;web.dev — Avoid large, complex layouts and layout thrashing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
