Eliminazione di oggetti in JavaScript


359

Sono un po 'confuso con l' deleteoperatore JavaScript . Prendi il seguente codice:

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

var foo = obj;

delete obj;

Dopo che questo pezzo di codice è stato eseguito, objè null, ma foofa ancora riferimento a un oggetto esattamente come obj. Immagino che questo oggetto sia lo stesso oggetto che ha fooindicato.

Questo mi confonde, perché mi aspettavo che la scrittura delete objcancellasse l'oggetto a cui objpuntava in memoria, non solo la variabile obj.

Questo perché Garbage Collector di JavaScript funziona su una base di mantenimento / rilascio, in modo che se non avessi altre variabili che puntano all'oggetto, verrebbe rimosso dalla memoria?

(A proposito, i miei test sono stati eseguiti in Safari 4.)



Articolo completo sulla parola chiave di eliminazione webcache.googleusercontent.com/…
Vitim.us

2
Il link sopra dovrebbe essere: perfectionkills.com/understanding-delete
johnmdonahue

1
@Steve Harrison delete non serve per cancellare un oggetto in javascript delete usa per rimuovere una chiave oggetto nel tuo caso l' var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;oggetto non viene cancellato controlla objelimina utilizzo: delete obj.helloTexte poi controllafoo now foo is an empty object
Umair Ahmed

2
@UmairAhmed, traduzione gratuita: "" " deletenon serve per eliminare oggetti in javascript. deleteViene usato per rimuovere una chiave oggetto. Nel tuo caso var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, l'oggetto non viene cancellato. Check obj. Quindi, esegui delete obj.helloTexte puoi vedere che fooora punta a un vuoto "" "
Pacerier

Risposte:


448

L'operatore delete cancella solo un riferimento, mai un oggetto stesso. Se eliminasse l'oggetto stesso, altri riferimenti rimanenti sarebbero penzolanti, come una cancellazione C ++. (E accedendo a uno di essi si verificherebbe un arresto anomalo. Renderli tutti impostati su null significherebbe avere un lavoro extra durante l'eliminazione o memoria aggiuntiva per ogni oggetto.)

Poiché Javascript viene raccolto in modo inutile, non è necessario eliminare gli oggetti stessi: verranno rimossi quando non è più possibile fare riferimento a essi.

Può essere utile eliminare i riferimenti a un oggetto se hai finito con loro, perché ciò fornisce al garbage collector maggiori informazioni su ciò che può essere recuperato. Se i riferimenti rimangono su un oggetto di grandi dimensioni, ciò può non essere reclamato, anche se il resto del programma non utilizza effettivamente quell'oggetto.


23
La deleteparola chiave funziona solo per le proprietà di un oggetto, non per le variabili. perfectionkills.com/understanding-delete
Alex Mund,

1
@AlexJM Sì, la prossima risposta di Guffa (e i suoi commenti) ne discute in dettaglio.
Jesse Rusak,

1
Una proprietà di un oggetto può essere un altro oggetto. Per esempio; var obj = {a: {}}; delete obj.a;
Alex Mund,

2
Ma ... le variabili non sono proprietà di window?
RedClover il

3
@Soaku non variabili locali. (ad esempio quelli dichiarati con var)
Jesse Rusak il

162

Il deletecomando non ha alcun effetto sulle variabili regolari, solo sulle proprietà. Dopo il deletecomando la proprietà non ha il valore null, non esiste affatto.

Se la proprietà è un riferimento a un oggetto, il deletecomando elimina la proprietà ma non l'oggetto. Il Garbage Collector si prenderà cura dell'oggetto se non ha altri riferimenti ad esso.

Esempio:

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'

(Testato in Firefox.)


39
Se questo viene eseguito nell'ambito globale, la xvariabile diventa solo una proprietà windowsull'oggetto globale e delete x;rimuove completamente la xvariabile.
Crescent Fresh,

18
@crescentfresh: è solo una proprietà se viene dichiarata implicitamente. Se è esplicitamente dichiarato come nell'esempio, è una variabile globale e non può essere eliminato.
Guffa,

4
@Tarynn: vedo, è qui che sta il problema. Se lo fai nella console, per qualche motivo xnon sarà una variabile corretta in alcuni browser, ma una proprietà windownell'oggetto. Questo ovviamente è un problema con la console e non riflette il modo in cui il codice viene normalmente eseguito.
Guffa,

2
@Guffa Dopo una serie di ricerche devo ammettere che probabilmente è stata una buona cosa non avere abbastanza rappresentante per votare in giù. Le mie più sincere scuse, e grazie per aver dedicato del tempo a mostrarmi cosa stava succedendo ... Ecco un'indagine approfondita: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn

2
@chao: capisco. Stai riscontrando lo stesso problema di Tarynn (vedi i commenti precedenti). Quando lo fai nella console, non funziona come nel codice reale.
Guffa,

56

Le "variabili dichiarate implicitamente" sono proprietà dell'oggetto globale, quindi cancellare funziona su di esse come funziona su qualsiasi proprietà. Le variabili dichiarate con var sono indistruttibili.


53
Non ho mai capito che var era così tosto.
Gavin,

1
Questo è un ottimo punto e un gotcha JS. Le persone si abituano a cancellare le finestre e poi si chiedono perché non possono fare lo stesso con le variabili locali.
welbornio,

2
Lo stesso vale per let.
Pacerier


4

delete non viene utilizzato per eliminare un oggetto in java Script.

deleteusato per rimuovere un object keynel tuo caso

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

l'oggetto non viene cancellato controlla che obj abbia ancora gli stessi valori elimina utilizzo:

delete obj.helloText

e quindi controllare obj, foo, entrambi sono oggetti vuoti.


2

Ho appena trovato un jsperf che potresti considerare interessante alla luce di questa faccenda. (potrebbe essere utile tenerlo in giro per completare l'immagine)

Confronta l' eliminazione , l'impostazione null e l'impostazione indefinita .

Ma tieni presente che verifica il caso quando elimini / imposti la proprietà molte volte.



1

IE da 5 a 8 presenta un bug in cui l'utilizzo di delete sulle proprietà di un oggetto host (Window, Global, DOM ecc.) Genera TypeError "L'oggetto non supporta questa azione".

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
}

In seguito, se è necessario verificare dove la proprietà ha un significato, utilizzare l'intero valore el.foo !== undefinedperché "foo" in el restituirà sempre true in IE.

Se hai davvero bisogno che la proprietà scompaia davvero ...

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 è necessario utilizzare l'oggetto host con API host ...

el.parent.removeChild(el._host);

1

Mi sono imbattuto in questo articolo nella mia ricerca di questa stessa risposta. Quello che ho finito per fare è semplicemente estrarre obj.pop()tutti i valori / oggetti memorizzati nel mio oggetto in modo da poter riutilizzare l'oggetto. Non sono sicuro se questa è una cattiva pratica o no. Questa tecnica mi è stata utile per testare il mio codice con gli strumenti Chrome Dev o FireFox Web Console.


1

Questo lavoro per me, sebbene non sia una buona pratica. Elimina semplicemente tutto l'elemento associato a cui appartiene l'oggetto.

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

qual è la migliore pratica? Ricordo di aver letto che l'operatore di eliminazione non era il migliore per eliminare le proprietà degli oggetti. Credo di averlo letto nel libro JavaScript di Crockford, ma al momento non riesco a cercarlo.
zero_cool

0

L'impostazione di una variabile per nullassicurarsi di interrompere qualsiasi riferimento agli oggetti in tutti i browser, inclusi riferimenti circolari tra elementi DOM e ambiti Javascript. Usando il deletecomando stiamo contrassegnando gli oggetti da cancellare alla prossima esecuzione della Garbage Collection, ma se ci sono più variabili che fanno riferimento allo stesso oggetto, l'eliminazione di una singola variabile NON libererà l'oggetto, rimuoverà semplicemente il collegamento tra quella variabile e l'oggetto. E alla prossima esecuzione della Garbage Collection, verrà pulita solo la variabile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.