O que é coleta de lixo JavaScript? O que é importante para um programador da Web entender sobre a coleta de lixo JavaScript, a fim de escrever um código melhor?
297
O que é coleta de lixo JavaScript? O que é importante para um programador da Web entender sobre a coleta de lixo JavaScript, a fim de escrever um código melhor?
Respostas:
Eric Lippert escreveu um post detalhado sobre este assunto há um tempo (comparando-o adicionalmente com o VBScript ). Mais precisamente, ele escreveu sobre o JScript , que é a implementação do ECMAScript da Microsoft, embora muito semelhante ao JavaScript. Eu imagino que você possa assumir que a grande maioria do comportamento seria a mesma para o mecanismo JavaScript do Internet Explorer. Obviamente, a implementação varia de navegador para navegador, embora eu suspeite que você possa usar vários princípios comuns e aplicá-los a outros navegadores.
Citado nessa página:
O principal objetivo da coleta de lixo é permitir que o programador não se preocupe com o gerenciamento de memória dos objetos que eles criam e usam, embora é claro que às vezes não há como evitá-lo - é sempre benéfico ter pelo menos uma idéia aproximada de como funciona a coleta de lixo. .
Nota histórica: uma revisão anterior da resposta tinha uma referência incorreta ao
delete
operador. Em JavaScript, odelete
operador remove uma propriedade de um objeto e é totalmente diferente dedelete
em C / C ++.fonte
delete
incorretamente; por exemplo, no primeiro exemplo, em vez dedelete foo
, você deve primeiro remover o ouvinte de evento viawindow.removeEventListener()
e depois usarfoo = null
para substituir a variável; no IE,delete window.foo
(mas nãodelete foo
) também teria funcionado sefoo
fosse global, mas mesmo assim não funcionaria no FF ou no Operadelete
é um operador unário (uma expressão), não uma declaração (ou seja:)delete 0, delete 0, delete 3
. Parece declaração quando expressa por uma expressão.Cuidado com referências circulares quando objetos DOM estiverem envolvidos:
Padrões de vazamento de memória em JavaScript
Lembre-se de que a memória só pode ser recuperada quando não há referências ativas ao objeto. Essa é uma armadilha comum com fechamentos e manipuladores de eventos, pois alguns mecanismos JS não verificam quais variáveis realmente são referenciadas nas funções internas e apenas mantêm todas as variáveis locais das funções anexas.
Aqui está um exemplo simples:
Uma implementação ingênua de JS não pode ser coletada
bigString
enquanto o manipulador de eventos estiver disponível. Existem várias maneiras de resolver esse problema, por exemplo, a configuraçãobigString = null
no final deinit()
(delete
não funcionará para variáveis locais e argumentos de função:delete
remove propriedades dos objetos e o objeto variável está inacessível - o ES5 no modo estrito acionará umReferenceError
se você tentar para excluir uma variável local!).Eu recomendo evitar o máximo possível de fechamentos desnecessários se você se preocupa com o consumo de memória.
fonte
Boa citação retirada de um blog
O componente DOM é "coletor de lixo", assim como o componente JScript, o que significa que, se você criar um objeto em um dos componentes e perder o controle, ele será limpo.
Por exemplo:
Quando você chama essa função, o componente JScript cria um objeto (chamado bigArray) que pode ser acessado na função. Assim que a função retorna, você "perde o controle" do bigArray porque não há mais como se referir a ela. Bem, o componente JScript percebe que você o perdeu e, portanto, o bigArray é limpo - sua memória é recuperada. O mesmo tipo de coisa funciona no componente DOM. Se você diz
document.createElement('div')
, ou algo semelhante, o componente DOM cria um objeto para você. Depois que você perde o controle desse objeto, o componente DOM limpa o relacionado.fonte
Que eu saiba, os objetos do JavaScript são coletados periodicamente quando não há referências restantes para o objeto. É algo que acontece automaticamente, mas se você quiser saber mais sobre como ele funciona, no nível C ++, faz sentido dar uma olhada no código-fonte WebKit ou V8
Normalmente, você não precisa pensar nisso, no entanto, em navegadores mais antigos, como o IE 5.5 e versões anteriores do IE 6, e talvez nas versões atuais, os fechamentos criariam referências circulares que, quando desmarcadas, acabariam consumindo memória. No caso em particular que quero dizer sobre fechamentos, foi quando você adicionou uma referência JavaScript a um objeto dom e um objeto a um objeto DOM que se referia novamente ao objeto JavaScript. Basicamente, ele nunca poderia ser coletado e, eventualmente, causaria instabilidade no sistema operacional em aplicativos de teste em loop para criar falhas. Na prática, esses vazamentos geralmente são pequenos, mas para manter seu código limpo, você deve excluir a referência de JavaScript para o objeto DOM.
Geralmente, é uma boa ideia usar a palavra-chave delete para des-referenciar imediatamente objetos grandes, como dados JSON, que você recebeu de volta e fez o que for necessário, especialmente no desenvolvimento da Web móvel. Isso faz com que a próxima varredura do GC remova esse objeto e libere sua memória.
fonte
mark-and-sweep
algoritmos de estilo mais recentes cuidam disso .coleta de lixo (GC) é uma forma de gerenciamento automático de memória, removendo os objetos que não são mais necessários.
qualquer processo relacionado à memória siga estas etapas:
1 - aloque seu espaço de memória necessário
2 - faça algum processamento
3 - libere esse espaço de memória
existem dois algoritmos principais usados para detectar quais objetos não são mais necessários.
Coleta de lixo com contagem de referência : esse algoritmo reduz a definição de "um objeto não é mais necessário" para "um objeto não tem outro objeto fazendo referência a ele", o objeto será removido se nenhum ponto de referência a ele
Algoritmo de marcação e varredura : conecte cada objeto à origem raiz. qualquer objeto não se conecta à raiz ou a outro objeto. este objeto será removido.
atualmente os navegadores mais modernos usando o segundo algoritmo.
fonte
Todos os mecanismos JavaScript possuem seus próprios coletores de lixo e podem ser diferentes. Na maioria das vezes, você não precisa lidar com eles, porque eles fazem o que deveriam.
Escrever um código melhor depende principalmente de quanto você conhece os princípios de programação, a linguagem e a implementação específica.
fonte
verifique isso
Em Javascript, você não se importa com alocação e desalocação de memória. Todo o problema é exigido ao intérprete Javascript. Ainda são possíveis vazamentos em Javascript, mas são erros do intérprete. Se você está interessado neste tópico, pode ler mais em www.memorymanagement.org
fonte
No Windows, você pode usar o Drip.exe para encontrar vazamentos de memória ou verificar se sua rotina de memória livre funciona.
É realmente simples, basta digitar o URL de um site e você verá o consumo de memória do renderizador IE integrado. Em seguida, clique em Atualizar. Se a memória aumentar, você encontrará um vazamento de memória em algum lugar da página da web. Mas isso também é muito útil para verificar se as rotinas para liberar memória funcionam no IE.
fonte
Os tipos de referência não armazenam o objeto diretamente na variável à qual está atribuído, portanto, a variável de objeto neste exemplo não contém realmente a instância do objeto. Em vez disso, ele mantém um ponteiro (ou referência) para o local na memória em que o objeto existe
se você atribuir uma variável a outra, cada variável obterá uma cópia do ponteiro e as duas ainda farão referência ao mesmo objeto na memória.
de Os princípios do JavaScript orientado a objetos - NICHOLAS C. ZAKAS
fonte