Objekte in JavaScript löschen

359

Ich bin ein bisschen verwirrt mit dem JavaScript- deleteOperator. Nehmen Sie den folgenden Code:

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

var foo = obj;

delete obj;

Nachdem dieser Code ausgeführt wurde, objist null, foobezieht sich aber immer noch auf ein Objekt genau wie obj. Ich vermute, dieses Objekt ist das gleiche Objekt, fooauf das gezeigt wurde.

Das verwirrt mich, weil ich erwartet habe, dass beim Schreiben delete objdas Objekt gelöscht wird, objauf das im Speicher verwiesen wird - nicht nur die Variable obj.

Ist das , weil von JavaScript Garbage Collector arbeitet an einer behalten / Release - Basis, so dass , wenn ich keine andere Variablen habe auf das Objekt zeigen, es würde aus dem Speicher entfernt werden?

(Meine Tests wurden übrigens in Safari 4 durchgeführt.)

Steve Harrison
quelle
Vollständiger Artikel über das Löschschlüsselwort webcache.googleusercontent.com/…
Vitim.us
2
Link oben sollte sein: perfectionkills.com/understanding-delete
johnmdonahue
1
@Steve Harrison löschen ist nicht zum Löschen eines Objekts in Javascript löschen verwenden zum Entfernen eines Objektschlüssels in Ihrem Fall var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;Objekt wird nicht gelöscht überprüfen objlöschen Verwendung: delete obj.helloTextund dann überprüfenfoo now foo is an empty object
Umair Ahmed
2
@UmairAhmed, Freie Übersetzung: „““ deleteist nicht für Objekte in Javascript zu löschen. deleteVerwendet wird , einen Objektschlüssel zum Entfernen In Ihrem Fall. var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, Wird das Objekt nicht gelöscht wird , überprüfen. Als objnächstes laufen. delete obj.helloTextUnd Sie können sehen , dass foonun auf ein leeres Objekt. "" "
Pacerier

Antworten:

448

Der Löschoperator löscht nur eine Referenz, niemals ein Objekt selbst. Wenn das Objekt selbst gelöscht würde, würden andere verbleibende Referenzen baumeln, wie z. B. ein C ++ - Löschvorgang. (Und der Zugriff auf eines von ihnen würde einen Absturz verursachen. Wenn sie alle null werden, bedeutet dies zusätzliche Arbeit beim Löschen oder zusätzlichen Speicher für jedes Objekt.)

Da es sich bei Javascript um Müll handelt, müssen Sie Objekte nicht selbst löschen. Sie werden entfernt, wenn keine Möglichkeit mehr besteht, auf sie zu verweisen.

Es kann nützlich sein, Verweise auf ein Objekt zu löschen, wenn Sie damit fertig sind, da dies dem Garbage Collector mehr Informationen darüber gibt, was zurückgefordert werden kann. Wenn Verweise auf ein großes Objekt verbleiben, kann dies dazu führen, dass es nicht zurückgefordert wird - auch wenn der Rest Ihres Programms dieses Objekt nicht tatsächlich verwendet.

Jesse Rusak
quelle
23
Das deleteSchlüsselwort funktioniert nur für Eigenschaften eines Objekts, nicht für Variablen. perfektionkills.com/understanding-delete
Alex Mund
1
@AlexJM Ja, die nächste Antwort von Guffa (und seine Kommentare) diskutiert dies ausführlich.
Jesse Rusak
1
Eine Eigenschaft eines Objekts kann ein anderes Objekt sein. Zum Beispiel; var obj = {a: {}}; delete obj.a;
Alex Mund
2
Aber ... sind Variablen nicht tatsächlich Eigenschaften von window?
RedClover
3
@ Soaku keine lokalen Variablen. (zB diejenigen, die mit erklärt wurden var)
Jesse Rusak
162

Der deleteBefehl hat keine Auswirkung auf reguläre Variablen, nur auf Eigenschaften. Nach dem deleteBefehl hat die Eigenschaft nicht den Wert null, sie existiert überhaupt nicht.

Wenn die Eigenschaft eine Objektreferenz ist, deletelöscht der Befehl die Eigenschaft, nicht jedoch das Objekt. Der Garbage Collector kümmert sich um das Objekt, wenn er keine weiteren Verweise darauf hat.

Beispiel:

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'

(In Firefox getestet.)

Guffa
quelle
39
Wenn dies im globalen Bereich ausgeführt wird, wird Ihre xVariable nur eine Eigenschaft des globalen windowObjekts und delete x;entfernt die xVariable tatsächlich vollständig.
Crescent Fresh
18
@crescentfresh: Es ist nur eine Eigenschaft, wenn sie implizit deklariert ist. Wenn es explizit wie im Beispiel deklariert ist, ist es eine globale Variable und kann nicht gelöscht werden.
Guffa
4
@ Tarynn: Ich verstehe, dort liegt das Problem. Wenn Sie dies in der Konsole tun, ist dies aus irgendeinem Grund xin einigen Browsern keine richtige Variable, sondern eine Eigenschaft im windowObjekt. Dies ist natürlich ein Problem mit der Konsole und spiegelt nicht wider, wie Code normalerweise ausgeführt wird.
Guffa
2
@Guffa Nach ein paar Recherchen muss ich zugeben, dass es wahrscheinlich gut war, dass ich nicht genug Repräsentanten hatte, um abzustimmen. Meine aufrichtige Entschuldigung, und vielen Dank für die Zeit nehmen , um mich zu zeigen , was happeneing ... Hier ist ein eingehendes explination: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn
2
@chao: Ich verstehe. Sie haben das gleiche Problem wie Tarynn (siehe frühere Kommentare). Wenn Sie dies in der Konsole tun, funktioniert es nicht wie in echtem Code.
Guffa
56

"implizit deklarierte Variablen" sind Eigenschaften des globalen Objekts. Löschen funktioniert also mit ihnen wie mit jeder Eigenschaft. Mit var deklarierte Variablen sind unzerstörbar.

Alex
quelle
53
Ich hätte nie gedacht, dass Var so schlecht ist.
Gavin
1
Dies ist ein großartiger Punkt und ein JS-Gotcha. Die Leute gewöhnen sich daran, Fenstervariablen zu löschen, und fragen sich dann, warum sie mit lokalen Variablen nicht dasselbe tun können.
Welbornio
2
Gleiches gilt für let.
Pacerier
4

delete wird nicht zum Löschen eines Objekts in Java Script verwendet.

deletewird zum Entfernen eines object keyin Ihrem Fall verwendet

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

Objekt wird nicht gelöscht check obj nimmt immer noch die gleichen Werte an Verwendung löschen:

delete obj.helloText

und dann überprüfen obj, foo, ob beide leere Objekte sind.

Umair Ahmed
quelle
2

Ich habe gerade einen JSperf gefunden, den Sie angesichts dieser Angelegenheit vielleicht interessant finden. (Es könnte praktisch sein, es aufzubewahren, um das Bild zu vervollständigen.)

Es vergleicht Löschen , Setzen von Null und Setzen von Undefiniert .

Beachten Sie jedoch, dass der Fall getestet wird, wenn Sie Eigenschaften mehrmals löschen / festlegen.

Garek
quelle
1

IE 5 bis 8 haben einen Fehler, bei dem die Verwendung von "Löschen" für Eigenschaften eines Hostobjekts (Fenster, Global, DOM usw.) TypeError auslöst "Objekt unterstützt diese Aktion nicht".

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
}

Später, wenn Sie überprüfen müssen, wo die Eigenschaft eine Bedeutung hat, verwenden Sie den vollen Wert, el.foo !== undefinedda "foo" in el im IE immer true zurückgegeben wird.

Wenn Sie die Immobilie wirklich brauchen, um wirklich zu verschwinden ...

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

Wenn Sie das Host-Objekt mit der Host-API verwenden müssen ...

el.parent.removeChild(el._host);
Johndhutcheson
quelle
1

Ich bin bei meiner Suche nach derselben Antwort auf diesen Artikel gestoßen. Am Ende habe ich einfach obj.pop()alle in meinem Objekt gespeicherten Werte / Objekte entfernt, damit ich das Objekt wiederverwenden kann. Ich bin mir nicht sicher, ob dies eine schlechte Praxis ist oder nicht. Diese Technik hat sich für mich als nützlich erwiesen, um meinen Code in Chrome Dev-Tools oder in der FireFox-Webkonsole zu testen.

Craig London
quelle
1

Diese Arbeit für mich, obwohl es keine gute Praxis ist. Es werden einfach alle zugehörigen Elemente gelöscht, zu denen das Objekt gehört.

 for (element in homeService) {
          delete homeService[element];
  }
Weinstock Sagar
quelle
Was ist die beste Vorgehensweise? Ich erinnere mich, dass ich gelesen habe, dass der Löschoperator zum Löschen von Objekteigenschaften nicht am besten geeignet war. Ich glaube, ich habe dies in Crockfords JavaScript-Buch gelesen, kann es aber im Moment nicht ausgraben.
zero_cool
0

Durch Festlegen einer Variablen nullwird sichergestellt, dass Verweise auf Objekte in allen Browsern unterbrochen werden, einschließlich Zirkelverweisen zwischen den DOM-Elementen und den Javascript-Bereichen. Mit dem deleteBefehl markieren wir Objekte, die beim nächsten Durchlauf der Garbage-Auflistung gelöscht werden sollen. Wenn jedoch mehrere Variablen auf dasselbe Objekt verweisen, wird durch Löschen einer einzelnen Variablen das Objekt NICHT freigegeben, sondern nur die Verknüpfung zwischen dieser Variablen und entfernt das Objekt. Beim nächsten Durchlauf der Garbage Collection wird nur die Variable bereinigt.

Pedro Justo
quelle