Menghapus Objek dalam JavaScript

359

Saya agak bingung dengan deleteoperator JavaScript . Ambil bagian kode berikut:

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

var foo = obj;

delete obj;

Setelah potongan kode ini dieksekusi, objadalah null, tetapi foomasih mengacu pada objek persis seperti obj. Saya menduga objek ini adalah objek yang sama dengan yang fooditunjukkan.

Ini membingungkan saya, karena saya berharap tulisan itu delete objmenghapus objek yang objmenunjuk ke dalam memori — bukan hanya variabel obj.

Apakah ini karena JavaScript's Garbage Collector bekerja dengan basis retain / release, sehingga jika saya tidak memiliki variabel lain yang menunjuk ke objek, itu akan dihapus dari memori?

(Omong-omong, pengujian saya dilakukan di Safari 4.)

Steve Harrison
sumber
7
Untuk referensi Anda. developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…
Daniel A. White
Artikel lengkap tentang kata kunci hapus webcache.googleusercontent.com/...
Vitim.us
2
Tautan di atas harus: perfectionkills.com/understanding-delete
johnmdonahue
1
@Steve Harrison delete bukan untuk menghapus objek di javascript delete use untuk menghapus kunci objek di case case Anda var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;tidak dihapus periksa objhapus penggunaan: delete obj.helloTextdan kemudian centangfoo now foo is an empty object
Umair Ahmed
2
@UmairAhmed, Terjemahan gratis: "" " deletebukan untuk menghapus objek dalam javascript. deleteDigunakan untuk menghapus kunci objek. Dalam kasus Anda var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, objek tidak dihapus. Centang obj. Selanjutnya, jalankan delete obj.helloTextdan Anda dapat melihat bahwa foosekarang menunjuk ke kosong objek. "" "
Pacerier

Jawaban:

448

Operator hapus hanya menghapus referensi, tidak pernah menjadi objek itu sendiri. Jika itu menghapus objek itu sendiri, referensi lain yang tersisa akan menggantung, seperti penghapusan C ++. (Dan mengakses salah satunya akan menyebabkan crash. Untuk membuat semuanya menjadi nol berarti memiliki kerja ekstra saat menghapus atau memori tambahan untuk setiap objek.)

Karena Javascript adalah sampah yang dikumpulkan, Anda tidak perlu menghapus objek sendiri - mereka akan dihapus ketika tidak ada cara untuk merujuknya lagi.

Mungkin bermanfaat untuk menghapus referensi ke suatu objek jika Anda selesai dengan itu, karena ini memberi informasi lebih lanjut kepada pengumpul sampah tentang apa yang dapat direklamasi. Jika referensi tetap ke objek besar, ini dapat menyebabkannya tidak direklamasi - bahkan jika program Anda tidak benar-benar menggunakan objek itu.

Jesse Rusak
sumber
23
Kata deletekunci hanya berfungsi untuk properti objek, bukan variabel. perfectionkills.com/understanding-delete
Alex Mund
1
@AlexJM Ya, jawaban berikutnya dari Guffa (dan komentarnya) membahas hal ini secara terperinci.
Jesse Rusak
1
Properti dari suatu objek dapat berupa objek lain. Sebagai contoh; var obj = {a: {}}; delete obj.a;
Alex Mund
2
Tapi ... bukankah sebenarnya variabel itu properti window?
RedClover
3
@ Soaku bukan variabel lokal. (misalnya yang dideklarasikan dengan var)
Jesse Rusak
162

The deleteperintah tidak berpengaruh pada variabel biasa, hanya sifat. Setelah deleteperintah, properti tidak memiliki nilai null, itu tidak ada sama sekali.

Jika properti adalah referensi objek, deleteperintah menghapus properti tetapi bukan objek. Pengumpul sampah akan merawat objek jika tidak memiliki referensi lain untuk itu.

Contoh:

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'

(Diuji di Firefox.)

Guffa
sumber
39
Jika ini dieksekusi dalam lingkup global, xvariabel Anda menjadi hanya properti pada windowobjek global , dan delete x;benar-benar menghapus xvariabel sama sekali.
Crescent Fresh
18
@crescentfresh: Ini hanya properti jika dinyatakan secara implisit. Jika dinyatakan secara eksplisit seperti pada contoh, ini adalah variabel global dan tidak dapat dihapus.
Guffa
4
@ Tarynn: Begitu, di situlah masalahnya. Jika Anda melakukan ini di konsol, karena alasan tertentu xtidak akan menjadi variabel yang tepat di beberapa browser, tetapi properti di windowobjek. Ini tentu saja masalah dengan konsol, dan tidak mencerminkan bagaimana kode biasanya dieksekusi.
Guffa
2
@ Guffa Setelah banyak penelitian saya harus mengakui itu mungkin hal yang baik saya tidak punya cukup perwakilan untuk menurunkan suara. Permintaan maaf saya yang tulus, dan terima kasih telah meluangkan waktu untuk menunjukkan kepada saya apa yang membuat bahagia ... Berikut ini adalah eksplorasi mendalam: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn
2
@ chao: Begitu. Anda mengalami masalah yang sama dengan Tarynn (lihat komentar sebelumnya). Ketika Anda melakukan ini di konsol itu tidak bekerja sama dengan kode nyata.
Guffa
56

"variabel yang dideklarasikan secara implisit" adalah properti dari objek global, jadi hapus karya pada mereka seperti itu bekerja pada properti apa pun. Variabel yang dideklarasikan dengan var tidak bisa dihancurkan.

Alex
sumber
53
Saya tidak pernah menyadari bahwa var begitu buruk.
Gavin
1
Ini adalah poin yang bagus, dan gotcha JS. Orang-orang terbiasa menghapus var jendela dan kemudian bertanya-tanya mengapa mereka tidak dapat melakukan hal yang sama dengan variabel lokal.
welbornio
2
Sama berlaku untuk let.
Pacerier
4

delete tidak digunakan untuk menghapus objek dalam java Script.

deletedigunakan untuk menghapus object keydalam kasus Anda

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

objek tidak dihapus periksa obj masih menggunakan nilai yang sama dengan menghapus penggunaan:

delete obj.helloText

dan kemudian periksa obj, foo, keduanya adalah objek kosong.

Umair Ahmed
sumber
2

Baru saja menemukan jsperf yang mungkin Anda anggap menarik mengingat masalah ini. (Mungkin berguna untuk menyimpannya di sekitar untuk melengkapi gambar)

Ini membandingkan hapus , pengaturan nol dan pengaturan tidak ditentukan .

Tetapi perlu diingat bahwa itu menguji kasus ketika Anda menghapus / mengatur properti berkali-kali.

Garek
sumber
1

IE 5 hingga 8 memiliki bug di mana menggunakan delete pada properti dari objek host (Window, Global, DOM dll) melempar TypeError "objek tidak mendukung tindakan ini".

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
}

Nanti jika Anda perlu memeriksa di mana properti tersebut memiliki makna nilai penuh digunakan el.foo !== undefinedkarena "foo" in el akan selalu mengembalikan true di IE.

Jika Anda benar-benar membutuhkan properti untuk benar-benar menghilang ...

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

jika Anda perlu menggunakan objek host dengan host api ...

el.parent.removeChild(el._host);
johndhutcheson
sumber
1

Saya menemukan artikel ini dalam pencarian saya untuk jawaban yang sama. Apa yang akhirnya saya lakukan hanyalah memunculkan obj.pop()semua nilai / objek yang tersimpan di objek saya sehingga saya bisa menggunakan kembali objek tersebut. Tidak yakin apakah ini praktik yang buruk atau tidak. Teknik ini berguna bagi saya untuk menguji kode saya di alat Chrome Dev atau FireFox Web Console.

Craig London
sumber
1

Ini bekerja untuk saya, meskipun ini bukan praktik yang baik. Itu hanya menghapus semua elemen terkait dengan objek yang dimiliki.

 for (element in homeService) {
          delete homeService[element];
  }
anggur sagar
sumber
apa praktik terbaik? Saya ingat pernah membaca bahwa operator hapus bukan cara terbaik untuk menghapus properti objek. Saya percaya saya membaca ini di buku JavaScript milik Crockford, tetapi saat ini tidak bisa menggali.
zero_cool
0

Mengatur variabel untuk nullmemastikan untuk memecah referensi ke objek di semua browser termasuk referensi melingkar yang dibuat antara elemen DOM dan cakupan Javascript. Dengan menggunakan deleteperintah, kami menandai objek yang akan dihapus pada proses berikutnya dari pengumpulan Sampah, tetapi jika ada beberapa variabel yang merujuk objek yang sama, menghapus variabel tunggal TIDAK AKAN membebaskan objek, itu hanya akan menghapus hubungan antara variabel itu dan objek. Dan pada pengumpulan sampah berikutnya, hanya variabel yang akan dibersihkan.

Pedro Justo
sumber