Excluindo objetos em JavaScript


359

Estou um pouco confuso com o deleteoperador do JavaScript . Pegue o seguinte pedaço de código:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

Após a execução desse trecho de código, objé null, mas fooainda se refere a um objeto exatamente como obj. Eu estou supondo que este objeto é o mesmo objeto que fooapontou.

Isso me confunde, porque eu esperava que a escrita delete objexcluísse o objeto que objestava apontando na memória - não apenas a variável obj.

Isso ocorre porque o Garbage Collector do JavaScript está trabalhando com retenção / liberação, para que, se eu não tivesse outras variáveis ​​apontando para o objeto, ele seria removido da memória?

(A propósito, meus testes foram feitos no Safari 4.)



Artigo completo sobre a palavra-chave de exclusão webcache.googleusercontent.com/...
Vitim.us


11
@ Steve Harrison exclusão não é para excluir um objeto em uso de exclusão javascript para remover uma chave de objeto no seu caso var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;objeto não é excluído de verificação objde uso de exclusão: delete obj.helloTextem seguida, verificarfoo now foo is an empty object
Umair Ahmed

2
@UmairAhmed, tradução gratuita: "" " deletenão é para excluir objetos em javascript. deleteÉ usado para remover uma chave de objeto. No seu caso var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, o objeto não é excluído. Verifique obj. Em seguida, execute delete obj.helloTexte você pode ver que fooagora aponta para um vazio objeto. "" "
Pacerier 23/03

Respostas:


448

O operador delete exclui apenas uma referência, nunca um objeto em si. Se ele excluísse o próprio objeto, outras referências restantes estariam pendentes, como uma exclusão do C ++. (E acessar um deles causaria uma falha. Torná-los todos nulos significaria ter um trabalho extra ao excluir ou memória extra para cada objeto.)

Como o Javascript é coletado como lixo, você não precisa excluir os próprios objetos - eles serão removidos quando não houver mais como fazer referência a eles.

Pode ser útil excluir referências a um objeto se você terminar com elas, pois isso fornece ao coletor de lixo mais informações sobre o que pode ser recuperado. Se as referências permanecerem em um objeto grande, isso poderá não ser recuperado - mesmo que o restante do seu programa não use esse objeto.


23
A deletepalavra-chave funciona apenas para propriedades de um objeto, não para variáveis. perfectionkills.com/understanding-delete
Alex Mund

11
@AlexJM Sim, a próxima resposta de Guffa (e seus comentários) discute isso em detalhes.
Jesse Rusak

11
Uma propriedade de um objeto pode ser outro objeto. Por exemplo; var obj = {a: {}}; delete obj.a;
precisa

2
Mas ... as variáveis ​​não são realmente propriedades de window?
RedClover

3
@ Soaku não variáveis ​​locais. (por exemplo, aqueles com declarado var)
Jesse Rusak

162

O deletecomando não tem efeito sobre variáveis ​​regulares, apenas propriedades. Após o deletecomando, a propriedade não possui o valor null, não existe mais.

Se a propriedade for uma referência a objeto, o deletecomando excluirá a propriedade, mas não o objeto. O coletor de lixo cuidará do objeto se ele não tiver outras referências a ele.

Exemplo:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(Testado no Firefox.)


39
Se isso for executado no escopo global, sua xvariável se tornará apenas uma propriedade no windowobjeto global e delete x;removerá a xvariável completamente.
Crescent Fresh

18
@crescentfresh: É apenas uma propriedade se for declarada implicitamente. Se declarado explicitamente como no exemplo, é uma variável global e não pode ser excluída.
Guffa

4
@ Tarynn: Entendo, é aí que está o problema. Se você fizer isso no console, por algum motivo x, não será uma variável adequada em alguns navegadores, mas uma propriedade no windowobjeto. Obviamente, isso é um problema com o console e não reflete como o código é normalmente executado.
Guffa

2
@ Guffa Depois de um monte de pesquisa, tenho que admitir que provavelmente foi uma coisa boa que eu não tinha representante suficiente para votar. Minhas sinceras desculpas, e obrigado por tomar o tempo para mim o que estava happeneing mostrar ... Aqui é um explination aprofundada: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn

2
@chao: Entendo. Você está tendo o mesmo problema que Tarynn (veja comentários anteriores). Quando você faz isso no console, ele não funciona da mesma forma que no código real.
Guffa

56

"variáveis ​​declaradas implicitamente" são propriedades do objeto global, portanto, delete funciona nelas, assim como em qualquer propriedade. Variáveis ​​declaradas com var são indestrutíveis.


53
Eu nunca percebi que var era tão foda.
Gavin

11
Este é um ótimo ponto, e um JS pegou. As pessoas se acostumam a excluir vars de janela e depois se perguntam por que não podem fazer o mesmo com variáveis ​​locais.
welbornio

2
O mesmo vale para let.
Pacerier 23/03


4

delete não é usado para excluir um objeto no java Script.

deleteusado para remover um object keyno seu caso

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

O objeto não é excluído. Verifique se o objeto ainda aceita os mesmos valores. Excluir uso:

delete obj.helloText

e verifique obj, foo, ambos são objetos vazios.


2

Acabei de encontrar um jsperf que você pode considerar interessante à luz deste assunto. (pode ser útil mantê-lo por perto para completar a imagem)

Ele compara excluir , definindo nulo e definindo indefinido .

Mas lembre-se de que ele testa o caso quando você exclui / define propriedades muitas vezes.



1

O IE 5 a 8 possui um erro no qual o uso de delete nas propriedades de um objeto host (Window, Global, DOM etc) lança TypeError "o objeto não suporta esta ação".

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

Posteriormente, se você precisar verificar onde a propriedade tem um significado, use valor total, el.foo !== undefinedporque "foo" in el sempre retornará verdadeiro no IE.

Se você realmente precisa que a propriedade realmente desapareça ...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

se você precisar usar o objeto host com a API do host ...

el.parent.removeChild(el._host);

1

Eu me deparei com este artigo na minha busca por essa mesma resposta. O que acabei fazendo é apenas exibir obj.pop()todos os valores / objetos armazenados no meu objeto para que eu pudesse reutilizá-lo. Não tenho certeza se isso é uma má prática ou não. Essa técnica foi útil para eu testar meu código nas ferramentas de desenvolvimento do Chrome ou no FireFox Web Console.


1

Este trabalho para mim, embora não seja uma boa prática. Ele simplesmente exclui todos os elementos associados aos quais o objeto pertence.

 for (element in homeService) {
          delete homeService[element];
  }

qual é a melhor prática? Lembro-me de ler que o operador de exclusão não era o melhor para excluir propriedades de objetos. Acredito que li isso no livro JavaScript de Crockford, mas não consigo desenterrá-lo no momento.
zero_cool

0

Definir uma variável para nullgarantir que todas as referências a objetos sejam quebradas em todos os navegadores, incluindo referências circulares sendo feitas entre os elementos DOM e os escopos Javascript. Usando o deletecomando, estamos marcando objetos a serem limpos na próxima execução da coleta de lixo, mas se houver várias variáveis ​​referenciando o mesmo objeto, excluir uma única variável NÃO libertará o objeto, apenas removerá a ligação entre essa variável e o objeto. E na próxima execução da coleta de lixo, apenas a variável será limpa.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.