Introdução
Idiomas de baixo nível, como C, possuem primitivas de gerenciamento de memória de baixo nível, como Malloc () e Free (). Os primitivos de memória do JavaScript, por outro lado, são alocados quando variáveis (objetos, strings etc.) são criados e, em seguida, "automaticamente" libertados quando não estão mais em uso. O último é chamado de coleta de lixo. Esse "automático" está ofuscando e fornecendo uma ilusão de JavaScript (e outros idiomas de alto nível): eles podem ignorar o gerenciamento da memória.
Ciclo de vida da memória
Não importa a linguagem de programação, o ciclo de vida da memória é basicamente o mesmo:
1. Aloce a memória que você precisa
2. Use (leia, escreva)
3. Libere o PS: e "Coloque o elefante na geladeira" significa o mesmo
A primeira e a segunda parte do processo são claras em todos os idiomas. A última etapa é clara em idiomas de baixo nível, mas em idiomas de alto nível como o JavaScript, o último passo não está claro.
Alocação de memória para JavaScript
Inicialização variável
Para não incomodar os programadores com o problema da alocação, o JavaScript conclui a alocação de memória ao definir variáveis.
A cópia do código é a seguinte:
var n = 123;
var s = "Azerty";
var o = {
A: 1,
B: NULL
};
var a = [1, nulo, "sutiã"];
função f (a) {
retornar a + 2;
} // ALOCAR MEMÓRIA PARA FUNÇÕES (objetos chamáveis)
// As expressões de função também podem atribuir um objeto
ALHEELEMENT.ADDEVENTListener ('Click', function () {
algum momento.style.backgroundColor = 'azul';
}, false);
Alocação de memória através de chamadas de função
Algumas chamadas de função resultam na alocação da memória do objeto:
A cópia do código é a seguinte:
var d = new Date ();
var e = document.createElement ('div');
Alguns métodos atribuem novas variáveis ou novos objetos:
A cópia do código é a seguinte:
var s = "Azerty";
var s2 = s.substr (0, 3);
// porque a string é um invariante, o JavaScript pode não alocar memória, mas armazena apenas o intervalo de 0-3.
var a = ["Ouais ouais", "nan nan"];
var a2 = ["geração", "nan nan"];
var a3 = A.Concat (A2);
Uso de valores
O processo de uso dos valores é na verdade uma operação de leitura e gravação da alocação da memória, o que significa que uma variável ou o valor da propriedade de um objeto pode ser gravada ou mesmo os parâmetros de uma função podem ser passados.
Libertado quando a memória não é mais necessária
A maioria dos problemas de gerenciamento de memória está nesta fase. A tarefa mais difícil aqui é encontrar "a memória alocada não é mais necessária". Muitas vezes, exige que os desenvolvedores determinem qual peça de memória no programa não é mais necessária e o liberte.
O intérprete de idioma de alto nível está incorporado a um "coletor de lixo" e seu trabalho principal é rastrear a alocação e o uso da memória para que ele seja lançado automaticamente quando a memória alocada não estiver mais em uso. Esse processo é uma aproximação, porque é impossível determinar se uma determinada peça de memória precisa ser determinada (não pode ser resolvida por algum algoritmo).
Reciclagem de lixo
Como mencionado acima, é impossível determinar a questão de procurar automaticamente se alguma memória é "não é mais necessária". Portanto, a implementação da coleta de lixo só pode resolver problemas gerais com limitações. Esta seção explicará os conceitos necessários para entender os principais algoritmos de coleta de lixo e suas limitações.
Citar
Os algoritmos de coleta de lixo dependem principalmente do conceito de referência. Em um ambiente gerenciado pela memória, se um objeto tiver permissão para acessar outro objeto (implicitamente ou explicitamente), ele é chamado de objeto referente a outro objeto. Por exemplo, um objeto JavaScript tem uma referência ao seu protótipo (referência implícita) e uma referência às suas propriedades (referência explícita).
Aqui, o conceito de "objeto" não apenas objetos especiais de JavaScript, mas também o escopo da função (ou escopo lexical global).
Coleção de lixo de contagem de referência
Este é o algoritmo de coleta de lixo mais fácil. Esse algoritmo simplifica "se o objeto não é mais necessário" como "se o objeto tem outros objetos referenciados a ele". Se nenhuma referência apontar para o objeto (referência zero), o objeto será reciclado pelo mecanismo de coleta de lixo.
Por exemplo
A cópia do código é a seguinte:
var o = {
A: {
B: 2
}
};
// Dois objetos são criados, um é referenciado como o atributo do outro e o outro é atribuído à variável o
// obviamente, nenhum deles pode ser coletado por lixo
var o2 = o; // a variável O2 é a segunda referência a "este objeto"
o = 1;
var oa = o2.a;
// Agora, existem duas referências a "este objeto", um é O2 e o outro é OA
o2 = "yo";
// ele pode ser reciclado
// No entanto, o objeto de sua propriedade A ainda é referenciado pela OA, então não pode ser reciclado ainda
oa = nulo;
// pode ser coletado de lixo
Limitação: Referência de reciclagem
Esse algoritmo simples tem uma limitação de que, se um objeto se referir a outro (formando uma referência circular), eles podem "não precisar mais", mas não serão reciclados.
A cópia do código é a seguinte:
função f () {
var o = {};
var o2 = {};
OA = O2;
O2.a = O;
retornar "Azerty";
}
f ();
// Dois objetos são criados e referenciados um ao outro, formando um loop
// eles não deixarão o escopo da função depois de serem chamados
// para que eles sejam inúteis e podem ser reciclados
// No entanto, o algoritmo de contagem de referência leva em consideração que eles têm referências um ao outro pelo menos uma vez, para que não sejam reciclados
Exemplos práticos
Ou seja, 6, 7 reciclagem de contagem de referência nos objetos DOM. Um problema comum para eles são vazamentos de memória:
A cópia do código é a seguinte:
var div = document.createElement ("div");
div.OnClick = function () {
doSomething ();
};
// Div tem uma referência apontando para a propriedade de processamento de eventos OnClick
// O manuseio de eventos também tem uma referência à div que pode ser acessada no escopo da função
// Esta referência circular fará com que ambos os objetos sejam coletados de lixo
Algoritmo de limpeza de marcas
Esse algoritmo simplifica "se o objeto não é mais necessário" como "se o objeto está disponível".
Esse algoritmo assume definir um objeto chamado root (no JavaScript, o root é um objeto global). Regularmente, o coletor de lixo começará na raiz, encontrará todos os objetos referenciados da raiz e, em seguida, encontrará os objetos referenciados por esses objetos ... começando pela raiz, o coletor de lixo encontrará todos os objetos que podem ser obtidos e todos os objetos que não podem ser obtidos.
Esse algoritmo é melhor que o anterior, porque "objetos com zero referências" estão sempre indisponíveis, mas, pelo contrário, não é necessariamente verdadeiro, consulte "Referências circulares".
Desde 2012, todos os navegadores modernos usam o algoritmo de coleta de lixo-limite. Todas as melhorias no algoritmo de coleta de lixo JavaScript são baseadas em melhorias no algoritmo de limpeza de tags, sem melhorar o próprio algoritmo de limpeza de tags e sua definição simplificada de se o objeto não é mais necessário.
Referências circulares não são mais um problema
No exemplo acima, após o retorno da chamada da função, ambos os objetos não podem ser recuperados do objeto global. Portanto, eles serão reciclados pelo coletor de lixo.
O segundo exemplo também, uma vez que a div e seu processamento de eventos não podem ser recuperados da raiz, eles serão reciclados pelo coletor de lixo.
Limitação: os objetos precisam estar explicitamente indisponíveis
Embora isso seja uma limitação, raramente é quebrado, e é por isso que, na realidade, poucas pessoas se preocupam com o mecanismo de coleta de lixo.