web-dev-qa-db-fra.com

Suppression d'objets en JavaScript

Je suis un peu confus avec l'opérateur delete de JavaScript. Prenez le morceau de code suivant:

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

var foo = obj;

delete obj;

Une fois que cette partie de code a été exécutée, obj est null, mais foo fait toujours référence à un objet exactement comme obj. Je devine que cet objet est le même objet que celui que foo a pointé.

Cela me rend confus, car je m'attendais à ce que l'écriture delete obj supprime l'objet que obj pointait en mémoire, pas seulement la variable obj.

Est-ce parce que le récupérateur de déchets de JavaScript fonctionne sur une base retenue/édition, de sorte que si je n'avais aucune autre variable pointant sur l'objet, elle le ferait être supprimé de la mémoire?

(Au fait, mes tests ont été effectués dans Safari 4.)

351
Steve Harrison

L'opérateur delete supprime uniquement une référence, jamais un objet lui-même. S'il supprimait l'objet lui-même, les autres références restantes seraient suspendues, comme une suppression C++. (Et accéder à l'un d'entre eux provoquerait un crash. Les rendre tous nuls signifierait un travail supplémentaire lors de la suppression ou de la mémoire supplémentaire pour chaque objet.)

Étant donné que Javascript est mis au rebut, vous n'avez pas besoin de supprimer les objets eux-mêmes. Ils seront supprimés lorsqu'il n'y aura plus aucun moyen de s'y référer.

Il peut être utile de supprimer les références à un objet si vous en avez fini, car cela donne au garbage collector plus d’informations sur ce qui peut être récupéré. S'il reste des références à un objet volumineux, cela peut entraîner sa non récupération, même si le reste de votre programme n'utilise pas réellement cet objet.

440
Jesse Rusak

La commande delete n'a aucun effet sur les variables normales, mais uniquement sur les propriétés. Après la commande delete, la propriété n'a pas la valeur null, elle n'existe pas du tout.

Si la propriété est une référence d'objet, la commande delete supprime la propriété mais pas l'objet. Le ramasse-miettes se chargera de l'objet s'il n'y a pas d'autres références.

Exemple:

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'

(Testé dans Firefox.)

157
Guffa

"Les variables déclarées implicitement" sont des propriétés de l'objet global. Par conséquent, delete fonctionne sur celles-ci comme sur n'importe quelle propriété. Les variables déclarées avec var sont indestructibles.

54
Alex

Venant de la documentation Mozilla, "Vous pouvez utiliser l'opérateur de suppression pour supprimer les variables déclarées implicitement, mais pas celles déclarées avec l'instruction var."

Voici le lien: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

23
David Ackerman

basé sur la réponse de @Guffa. J'ai trouvé la méthode suivante qui fonctionne pour moi:

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

obj = null;

delete obj;

En définissant obj sur null, vous supprimez toute la référence, puis vous pouvez le supprimer complètement.

Je ne l'ai pas testé sur un autre navigateur, mais cela fonctionne dans phonegap 1.7.0.

6
Bohr

delete n'est pas utilisé pour supprimer un objet dans Java Script.

delete utilisé pour supprimer un object key dans votre cas

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

l'objet n'est pas supprimé cocher obj prend toujours les mêmes valeurs delete usage:

delete obj.helloText

puis vérifiez obj, foo, les deux sont des objets vides.

4
Umair Ahmed

Outre les questions du GC, pour les performances, il convient de prendre en compte les optimisations que le navigateur peut effectuer en arrière-plan ->

http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

Il semble préférable d’annuler la référence plutôt que de la supprimer, car cela pourrait modifier l’utilisation de la 'classe' en coulisse Chrome.

2
sksizer

Je viens de trouver un jsperf que vous pouvez considérer intéressant à la lumière de cette affaire. (il pourrait être utile de le garder pour compléter le tableau)

Il compare supprimer , régler null et réglage non défini .

Mais gardez à l'esprit qu'il teste le cas lorsque vous supprimez/définissez une propriété plusieurs fois.

2
garek

IE 5 à 8 a un bogue où l'utilisation de delete sur les propriétés d'un objet Host (Window, Global, DOM, etc.) lève TypeError "l'objet ne supporte pas cette action".

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
}

Si vous devez vérifier plus tard si la propriété a une signification, utilisez el.foo !== undefined car "foo" in el renverra toujours la valeur true dans IE.

Si vous avez vraiment besoin que la propriété disparaisse vraiment ...

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

si vous avez besoin d'utiliser l'objet Host avec Host api ...

el.parent.removeChild(el._Host);
1
johndhutcheson

Je suis tombé sur cet article dans ma recherche de cette même réponse. Ce que j'ai fini par faire est de simplement extraire obj.pop() toutes les valeurs/objets stockés dans mon objet afin de pouvoir le réutiliser. Pas sûr que ce soit une mauvaise pratique ou non. Cette technique m'a été utile pour tester mon code dans ChromeDev Tools ou la console Web FireFox.

1
Craig London

Cela fonctionne pour moi, bien que ce ne soit pas une bonne pratique. Il supprime simplement tous les éléments associés auxquels appartient l'objet.

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

Définir une variable sur null permet de casser toutes les références aux objets de tous les navigateurs, y compris les références circulaires entre les éléments DOM et les étendues Javascript. En utilisant la commande delete, nous marquons les objets à effacer lors de la prochaine exécution de la collection Garbage, mais s'il existe plusieurs variables référençant le même objet, la suppression d'une seule variable NE libère PAS l'objet, elle supprimera simplement le lien entre cette variable et l'objet. Et lors de la prochaine exécution de la récupération de place, seule la variable sera nettoyée.

0
Pedro Justo